javassist使用
Java bytecode engineering toolkit since 1999Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由日本的 Shigeru Chiba 所创建的,它已加入了开放源代码 JBoss 应用服务器项目,通过使用 Javassist 对字节码操作为 JBoss 实现动态"AOP"框架。关于java字节码的处理,目前有很多工具,如bcel,ASM。
Java bytecode engineering toolkit since 1999
Javassist是一个开源的分析、编辑和创建Java字节码的类库。是由日本的 Shigeru Chiba 所创建的,它已加入了开放源代码 JBoss 应用服务器项目,通过使用 Javassist 对字节码操作为 JBoss 实现动态"AOP"框架。
关于java字节码的处理,目前有很多工具,如bcel,ASM。不过这些都需要直接跟虚拟机指令打交道。如果你不想了解虚拟机指令,可以采用javassist。javassist是jboss的一个子项目,其主要的优点在于简单、快速。直接使用java编码的形式,而不需要了解虚拟机指令,就能动态改变类的结构,或者动态生成类。
Javassist (Java Programming Assistant) makes Java bytecode manipulation simple. It is a class library for editing bytecodes in Java; it enables Java programs to define a new class at runtime and to modify a class file when the JVM loads it.
Javassist(Java Programming Assistant)使Java字节码操作变得简单。它是一个用于在Java中编辑字节码的类库;它使Java程序能够在运行时定义新类,并在JVM加载时修改类文件。
1.javassist 获取类的基本信息
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("org.example.domain.Student");
//得到字节码
byte[] bytes = ctClass.toBytecode();
//获取长度
System.out.println(bytes.length);
//获取类名
System.out.println(ctClass.getName());
//获取简要类名
System.out.println(ctClass.getSimpleName());
//获取父类
System.out.println(ctClass.getSuperclass().getName());
//获取接口
System.out.println(Arrays.toString(ctClass.getInterfaces()));
//获取构造方法
for(CtConstructor ctConstructor : ctClass.getConstructors()){
System.out.println("构造方法 "+ctConstructor.getName());
}
//获取方法
for(CtMethod ctMethod : ctClass.getMethods()){
System.out.println("所有方法:"+ctMethod.getName());
}
for(CtMethod ctMethod : ctClass.getDeclaredMethods()){
System.out.println("定义方法:"+ctMethod.getName());
}
for(CtField ctField : ctClass.getDeclaredFields()){
System.out.println("定义属性:"+ctField.getName());
System.out.println("属性类型:"+ctField.getType());
}
2.在原有的方法后面添加自己定义的
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("org.example.domain.Student");
CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
ctMethod.insertBefore("System.out.println(\"调用前1\");");
ctMethod.insertAt(20094, "System.out.println(\"在指定行插入代码\");");//貌似行号胡乱写也可以
ctMethod.insertAfter("{" + "System.out.println(\"你好:\" + this.getName()+\",今年:\"+this.getAge());" + "}");
Class newClass = ctClass.toClass();
Student student = (Student) newClass.newInstance();
student.setName("张三");
student.setAge(18);
student.sayHello();
注意,如果使用 JDK9 以下的JDK ,同时使用 3.20.0-GA 以上版本的 Javassist,调用 toClass 方法会报 StackWalker 异常
3.javassist 在声明的方法中重新定义内容
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.get("org.example.domain.Student");
CtMethod ctMethod = ctClass.getDeclaredMethod("hello",new CtClass[]{classPool.get("java.lang.String")});
ctMethod.setBody("{" + "System.out.println(\"你好:\" + $1);" + "}");
//ctClass.writeFile("C:\\installsoft\\");
//加载修改后的类,注意:必须保证调用前此类未加载
ctClass.toClass();
new Student().hello("包青天");```
4.javassist 创建类 属性 方法 构造器 注解
ClassPool classPool = ClassPool.getDefault();
CtClass ctClass = classPool.makeClass(“org.example.domain.User”);
//创建属性
ctClass.addField(CtField.make("private int id;",ctClass));
ctClass.addField(CtField.make("private String name;",ctClass));
CtField ctField = new CtField(CtClass.intType,"age",ctClass);
ctField.setModifiers(Modifier.PRIVATE);
ctClass.addField(ctField);
ctClass.addMethod(CtNewMethod.getter("getAge",ctField));
ctClass.addMethod(CtNewMethod.setter("setAge",ctField));
//创建方法
ctClass.addMethod(CtMethod.make("public String getName(){return name;}",ctClass));
ctClass.addMethod(CtMethod.make("public void setName(String name){this.name=name;}",ctClass));
//创建方法
CtClass[] ctClasses = new CtClass[]{CtClass.intType};
// 返回值,方法名,参数,对象
CtMethod ctMethod = new CtMethod(CtClass.intType,"setId",ctClasses,ctClass);
//访问范围
ctMethod.setModifiers(Modifier.PUBLIC);
//方法体
ctMethod.setBody("{return $1;}");
ctClass.addMethod(ctMethod);
//添加注解
ClassFile classFile = ctClass.getClassFile();
ConstPool constPool = classFile.getConstPool();
AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool,AnnotationsAttribute.visibleTag);
//创建要添加的注解
Annotation annotation = new Annotation(SerializedName.class.getCanonicalName(),constPool);
//设置注解中的属性和值
annotation.addMemberValue("value",new StringMemberValue("p",constPool));
//把这个注解添加到AnnotationsAttribute对象里面
annotationsAttribute.addAnnotation(annotation);
//把这个对象放到要打上注解的字段/类上
ctField.getFieldInfo().addAttribute(annotationsAttribute);
//添加构造器
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{ CtClass.intType,classPool.get("java.lang.String")},ctClass);
ctConstructor.setBody("{this.id = id;this.name = name;}");
ctClass.addConstructor(ctConstructor);
ctClass.writeFile("C:\\installsoft\\springbootdisruptor\\src\\main\\java");
更多推荐
所有评论(0)