Java byte-buddy动态生成子类,Java 动态增加属性和方法

================================

©Copyright 蕃薯耀 2022-08-31

https://www.cnblogs.com/fanshuyao/

 

Java 使用byte-buddy实现动态生成子类,动态增加属性和方法

一、byte-buddy官网地址

https://bytebuddy.net/

https://github.com/raphw/byte-buddy

 

 

二、引入byte-buddy的Maven依赖

        <dependency>
            <groupId>net.bytebuddy</groupId>
            <artifactId>byte-buddy</artifactId>
        </dependency>

 

 

三、byte-buddy一个简单的例子

Class<?> dynamicType = new ByteBuddy()
  .subclass(Object.class)
  .method(ElementMatchers.named("toString"))
  .intercept(FixedValue.value("Hello World!"))
  .make()
  .load(getClass().getClassLoader())
  .getLoaded();
assertThat(dynamicType.newInstance().toString(), is("Hello World!"));

 

subclass:声明继承的父类

method:匹配方法

intercept:拦截method匹配后的返回值

 

 

 

四、byte-buddy动态生成子类、属性、方法

    public Object handleEntity(Object data) {
        if(data == null) {
            return data;
        }
        
        ObjectMapper mapper = new ObjectMapper();
        
        String json = "{}";
        try {
            //解决@JsonFormat注解解析不了的问题
            json = mapper.writeValueAsString(data);
            
        } catch (JsonProcessingException e) {
            log.error("Json解析失败:" + e);
            log.error("Json解析失败,data=" + data);
        }
        
        Builder<? extends Object> builder = new ByteBuddy()
                //.redefine(data.getClass())
              .subclass(data.getClass())
              //.modifiers(Opcodes.ACC_PUBLIC)
              //.name("com.builder.vo." + ClassUtil.getClassName(data, true) + "Sub")
              .name(ClassUtil.getClassName(data, false) + "DynamicTypeBuilder")
        ;
        
        
        JSONObject jsonObject = JSONObject.parseObject(json);
        
        for (Field field : ReflectUtil.getFields(data.getClass())) {
            
            Object o = jsonObject.getObject(field.getName(), field.getType());
            
            if(o != null) {
                builder = builder
                        //.defineProperty(field.getName(), field.getType())//声明;getter和setter方法
                        .method(ElementMatchers.named("get" + StringUtils.capitalize(field.getName())))
                        .intercept(FixedValue.value(o))
                ;
            }
            
            if (field.getAnnotation(Dict.class) != null) {
                String dictCode = field.getAnnotation(Dict.class).dictCode();
                String dictName = field.getAnnotation(Dict.class).dictName();
                if(StringUtils.isBlank(dictName)) {
                    dictName = field.getName() + DICT_SUFFIX;
                }
                
                String dictValue = String.valueOf(jsonObject.get(field.getName()));
                
                //翻译字典值对应的text值
                Optional<String> textValue = Optional.ofNullable(dictCacheService.getText(dictCode, dictValue));
                //jsonObject.put(dictName, textValue.orElse("未知"));
                
                builder = builder.defineField(dictName, String.class, Modifier.PRIVATE)//.value(value)
                    .defineMethod("get" + StringUtils.capitalize(dictName), String.class, Modifier.PUBLIC)
                    .intercept(FixedValue.value(textValue.orElse("--")))
                ;
                
            }
            
        }
        
        Object returnObject = null;
        try {
            
            /*
            //保存生成的类class文件到某个文件夹
            try {
                builder.make().saveIn(new File("c:/0"));
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            */
            
            returnObject =  builder.make()
                .load(getClass().getClassLoader())
                //.load(getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
                .getLoaded()
                .newInstance()
            ;
            
        } catch (InstantiationException e) {
            log.error("字典转换出错", e);
            
        } catch (IllegalAccessException e) {
            log.error("字典转换出错", e);
        }
        
        //CglibUtil.copy(data, returnObject);
        
        return returnObject;
        
        //return jsonObject;
        //return data;
    }

 

defineField:定义字段,即增加字段

defineMethod:定义方法,即增加方法

intercept:拦截defineMethod,设置返回值或者调用的方法

 

 

 

 

(时间宝贵,分享不易,捐赠回馈,^_^)

 

================================

©Copyright 蕃薯耀 2022-08-31

https://www.cnblogs.com/fanshuyao/

posted @ 2022-08-31 16:55  蕃薯耀  阅读(1063)  评论(1编辑  收藏  举报