美文网首页java
javassist动态增加类属性

javassist动态增加类属性

作者: 修行者12138 | 来源:发表于2020-09-28 20:44 被阅读0次

引入pom

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

Student.class

@Data
public class Student{
    @Id
    private Long id;

    private String studentName;

    private Integer age;
}
@Test
public void test1() throws Exception {
    Student student = new Student();
    student.setStudentName("ltm");
    student.setAge(99);

    // 需要新增的属性
    Map<String, Object> newFieldMap = new HashMap<>();
    newFieldMap.put("className", "1班");

    ClassPool pool = ClassPool.getDefault();
    // 注意: 不能用pool.get(Student.class.getName()),否则报错attempted  duplicate class definition for name,原因是同个Class不能在同个ClassLoader中加载两次
    CtClass ctClass = pool.get(student.getClass().getName());

    // 给class新增属性
    for(String fieldName: newFieldMap.keySet()) {
        // 字段类型
        String fieldType = newFieldMap.get(fieldName).getClass().getName();
        // 创建新字段
        CtField ctField = new CtField(pool.get(fieldType), fieldName, ctClass);
        ctField.setModifiers(Modifier.PRIVATE);
        ctClass.addField(ctField);
    }

    // 同个Class不能在同个ClassLoader中加载两次,所以需要使用javassist提供的ClassLoader
    Loader classLoader = new Loader(pool);
    // 生成新的字节码
    Class<?> newClass = classLoader.loadClass(ctClass.getName());
    // 用新的字节码创建新的对象
    Object newObject = newClass.newInstance();

    // 设置原有属性的值
    for (Field oldField: student.getClass().getDeclaredFields()) {
        // 跳过final属性,因为final属性无法修改
        if (java.lang.reflect.Modifier.isFinal(oldField.getModifiers())) {
            continue;
        }
        oldField.setAccessible(true);
        Field newField = newClass.getDeclaredField(oldField.getName());
        newField.setAccessible(true);
        newField.set(newObject, oldField.get(student));
    }

    // 设置新增属性的值
    for (String fieldName: newFieldMap.keySet()) {
        Field field = newClass.getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(newObject, newFieldMap.get(fieldName));
    }

    for (Field field: newClass.getDeclaredFields()) {
        field.setAccessible(true);
        System.out.println(field.getName() + ": " + field.get(newObject));
    }
}

输出结果
id: null
studentName: ltm
age: 99
className: 1班

本方案并不是在已实例化的对象上直接增加属性,而是修改字节码,给字节码增加属性,用新的字节码创建新的对象,然后给新对象的属性赋值。

相关文章

  • android 热修复之类加载机制

    文章目标 Android类加载机制介绍 javassist动态修改字节码 实现热补丁动态修复 Android类加载...

  • Java的动态机制---字节码操作

    字节码 1 动态生成新的类 动态改变类的结构 2 字节码操作库 BCEL ASM CGLIB Javassist ...

  • java动态增加方法

    java动态增加方法 借鉴了spring devtool的热部署思想,通过使用javassist或者cglib来实...

  • iOS-runtime实践

    目录动态添加一个类打印一个类的所有ivar, property 和 method给分类增加属性动态添加方法实现更换...

  • ES常用命令

    mapping映射 更改映射属性--禁止动态增加 更改映射属性--增加域

  • Bean复制工具

    Java因为是静态语言,所以要增加属性时,不能像动态语言那样,直接在对象上增加一个属性。而是需要修改原来的类,或者...

  • iOS中的runtime理解

    Runtime的使用:1.动态获取/创建类2.动态为一个类增加属性(关联对象)或方法3.在程序运行过程中遍历类中的...

  • Javassist 字节码插桩

    Javassist基础 Javassist 使您可以 检查、编辑以及创建Java 二进制类。Javassist 使...

  • Python:面向对象编程(进阶)

    类动态绑定方法与限定实例属性 类动态绑定方法 前面我们说了如何给类动态的添加属性,那么如何动态绑定方法呢?如下示例...

  • 使用ASM 框架为类动态增加属性

      有一个测试类Demo.class,现在需要给这个类增加一个属性private String name。   增...

网友评论

    本文标题:javassist动态增加类属性

    本文链接:https://www.haomeiwen.com/subject/ffweuktx.html