使用javassist增强实体并重新加载

最近项目有个需求,需要在全部实体上增加一个字段,并使用统一方法调用,就试着用javassist实现。

1、引入jar包

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

2、新增方法

private T enhanceEntity(T old,String deleteUser) throws NotFoundException, CannotCompileException,
            ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
        String addFieldName = "deleteUser";
        boolean enhance = false;
        //增强实体类
        ClassPool pool = ClassPool.getDefault();
        CtClass ctClass = pool.get(old.getClass().getName());
        CtField[] fields = ctClass.getDeclaredFields();
        for(CtField field : fields){
            if(addFieldName.equals(field.getName())){
                enhance = true;
                break;
            }
        }
        if(!enhance){
            //如果类被冻结,解冻
            if(ctClass.isFrozen()){
                ctClass.defrost();
            }
            //增加新字段
            CtField ctField = new CtField(pool.get(String.class.getName()), addFieldName, 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: old.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(old));
        }
        Field field = newClass.getDeclaredField(addFieldName);
        field.setAccessible(true);
        field.set(newObject, deleteUser);
        return (T)newObject;
    }

经过简单测试,可以实现需求,如果有缺陷或者问题,后续会继续跟进修改维护

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容