当前位置: 代码迷 >> 综合 >> javassist 生成对象属性
  详细解决方案

javassist 生成对象属性

热度:67   发布时间:2024-01-30 20:45:45.0

java动态生成代码涉及到了字节码操作,通常 java 动态性两种常用的实现方式
1,字节码操作
2,反射。
运行时操作字节码可以实现如下功能
1,动态生成新的类。
2, 动态改变某个类的结构。
字节码操作 通常比反射开销小,性能高。

1.添加依赖

<dependency><groupId>org.javassist</groupId><artifactId>javassist</artifactId><version>3.27.0-GA</version>
</dependency>

2.添加代码

import javassist.*;import java.io.File;
import java.io.FileOutputStream;public class GenerateNewClassByJavassist {public static void main(String[] args) throws Exception{//ClassPool:CtClass对象的容器ClassPool pool = ClassPool.getDefault();//通过ClassPool生成一个public新类Emp.javaCtClass ctClass = pool.makeClass("com.study.javassist.Emp");//添加字段//首先添加字段private String enameCtField enameField = new CtField(pool.getCtClass("java.lang.String"),"ename",ctClass);enameField.setModifiers(Modifier.PRIVATE);ctClass.addField(enameField);//其次添加字段privtae int enoCtField enoField = new CtField(pool.getCtClass("int"),"eno",ctClass);enoField.setModifiers(Modifier.PRIVATE);ctClass.addField(enoField);//为字段ename和eno添加getXXX和setXXX方法ctClass.addMethod(CtNewMethod.getter("getEname", enameField));ctClass.addMethod(CtNewMethod.setter("setEname", enameField));ctClass.addMethod(CtNewMethod.getter("getEno", enoField));ctClass.addMethod(CtNewMethod.setter("setEno", enoField));//添加构造函数CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);//为构造函数设置函数体StringBuffer buffer = new StringBuffer();buffer.append("{\n").append("ename=\"yy\";\n").append("eno=001;\n}");ctConstructor.setBody(buffer.toString());//把构造函数添加到新的类中ctClass.addConstructor(ctConstructor);//添加自定义方法CtMethod ctMethod = new CtMethod(CtClass.voidType,"printInfo",new CtClass[]{},ctClass);//为自定义方法设置修饰符ctMethod.setModifiers(Modifier.PUBLIC);//为自定义方法设置函数体StringBuffer buffer2 = new StringBuffer();buffer2.append("{\nSystem.out.println(\"begin!\");\n").append("System.out.println(ename);\n").append("System.out.println(eno);\n").append("System.out.println(\"over!\");\n").append("}");ctMethod.setBody(buffer2.toString());ctClass.addMethod(ctMethod);//为了验证效果,下面使用反射执行方法printInfoClass<?> clazz = ctClass.toClass();Object obj = clazz.newInstance();obj.getClass().getMethod("printInfo", new Class[]{}).invoke(obj, new Object[]{});//把生成的class文件写入文件byte[] byteArr = ctClass.toBytecode();FileOutputStream fos = new FileOutputStream(new File("D://Emp.class"));fos.write(byteArr);fos.close();}
}

3.运行结果:

begin!
yy
1
over!

4.反编译Emp.class

package com.study.javassist;public class Emp {private String ename = "yy";private int eno = 1;public String getEname() {return this.ename;}public void setEname(String var1) {this.ename = var1;}public int getEno() {return this.eno;}public void setEno(int var1) {this.eno = var1;}public Emp() {}public void printInfo() {System.out.println("begin!");System.out.println(this.ename);System.out.println(this.eno);System.out.println("over!");}
}