我是靠谱客的博主 缓慢裙子,这篇文章主要介绍javassist动态创建类并添加注解,现在分享给大家,希望可以做个参考。

有一个场景我需要在一个类的一个字段上加上@JSONField(serialize = false),让它在转换成json字符串的时候忽略指定字段,可是这个类是通过javassist生成的,于是乎就有了下面的内容

依赖

复制代码
1
2
3
4
5
6
7
8
9
10
11
<dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.25.0-GA</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.25</version> </dependency>

创建一个类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.mytest; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.annotation.JSONField; import javassist.*; import javassist.bytecode.AnnotationsAttribute; import javassist.bytecode.ClassFile; import javassist.bytecode.ConstPool; import javassist.bytecode.annotation.Annotation; import javassist.bytecode.annotation.BooleanMemberValue; import org.junit.jupiter.api.Test; import java.lang.reflect.Method; /** * @Author: RR * @Date: 2021/1/6 10:22 */ public class JavassistTest { @Test public void test() throws Exception { //用javassist动态创建一个Person类,并将类存放在classLoader中 loadPerson(); //从classLoader中取出Person类的类对象 ClassLoader classLoader = ClassPool.getDefault().getClassLoader(); Class<?> clazz = classLoader.loadClass("com.mytest.Person"); //创建一个Person类的对象,并通过反射的形式给它设值 Object person = clazz.newInstance(); Method setAge = clazz.getMethod("setAge", Integer.class); Method setName = clazz.getMethod("setName", String.class); setAge.invoke(person, 1); setName.invoke(person, "名字"); //打印对象 System.out.println("toString:"+person); System.out.println("toJSONString:"+JSONObject.toJSONString(person)); } private void loadPerson() throws Exception{ //声明一个Person类 ClassPool pool = ClassPool.getDefault(); CtClass ctClass = pool.makeClass("com.mytest.Person"); /* 为Person类添加两个变量: private String name; private Integer age; */ CtField name = new CtField(pool.get(String.class.getCanonicalName()), "name", ctClass); name.setModifiers(Modifier.PRIVATE); ctClass.addField(name); CtField age = new CtField(pool.get(Integer.class.getCanonicalName()), "age", ctClass); age.setModifiers(Modifier.PRIVATE); ctClass.addField(age); //关于这段操作我也不太懂,都是零零散散地收集网上看到的,有大佬懂的话希望帮我解答解答~ ClassFile classFile = ctClass.getClassFile(); ConstPool constPool = classFile.getConstPool(); AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag); //创建要添加的注解 Annotation jsonFileAnnotation = new Annotation(JSONField.class.getCanonicalName(), constPool); //设置注解中的属性和值 jsonFileAnnotation.addMemberValue("serialize", new BooleanMemberValue(false, constPool)); //把这个注解放到一个AnnotationsAttribute对象里面 annotationsAttribute.addAnnotation(jsonFileAnnotation); //把这个对象怼到要打上这个注解的字段/类上面 age.getFieldInfo().addAttribute(annotationsAttribute); //添加getter setter方法 ctClass.addMethod(CtNewMethod.setter("setName", name)); ctClass.addMethod(CtNewMethod.setter("setAge", age)); ctClass.addMethod(CtNewMethod.getter("getName", name)); ctClass.addMethod(CtNewMethod.getter("getAge", age)); //添加toString方法 StringBuilder builder = new StringBuilder(); builder.append("return "Person{" +n" + " "name='" + name + '\'' +n" + " ", age='" + age + '\'' +n" + " '}';"); CtMethod toStringMethod = new CtMethod(pool.get("java.lang.String"), "toString", null, ctClass); toStringMethod.setBody(builder.toString()); ctClass.addMethod(toStringMethod); //生成字节码文件,方便查看创建出来的类的结果 ctClass.writeFile("D:\IDEAProject\MyTestProject\target\test-classes"); // 也可以用这种方式,不用生成.class文件也可以直接使用动态生成的类 // ctClass.toClass(ClassPool.getDefault().getClassLoader(), Class.class.getProtectionDomain()); } }
  1. 在代码后面的ctClass.writeFile方法,可以把路径修改成自己想要的路径,运行这个测试类,可以找到生成的.class文件,内容如下
复制代码
1
2
3
4
5
6
7
8
public class Person { private String name; @JSONField( serialize = false ) private Integer age; //getter setter和无参构造方法省略
  1. 也可以看到我们测试类打印出来的person对象,只打印出name字段的信息,age字段成功被我们打入注解然后忽略掉了
复制代码
1
2
3
toString:Person{name='名字', age='1'} toJSONString:{"name":"名字"}

最后

以上就是缓慢裙子最近收集整理的关于javassist动态创建类并添加注解的全部内容,更多相关javassist动态创建类并添加注解内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部