SpringBoot使用cglib动态给对象设置属性

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanGenerator;
import org.springframework.cglib.beans.BeanMap;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * @author : 
 * @date : 
 * DESCRIPTION: 动态为对象增加属性工具类
 */

@Slf4j
public class DynamicAddParamUtil {

    /**
     * 使用表达式,去去掉参数前缀 $cglib_prop_
     */
    private static final Pattern COMPILE = Pattern.compile("^(.*)cglib_prop_(.*)$");

/**
     * @param object    旧的对象带值
     * @param addMap    动态需要添加的属性和属性类型
     * @param addValMap 动态需要添加的属性和属性值
     * @return 新的对象
     * @throws
     */
    public static Object dynamicClass(Object object, Map<String, Object> addMap, Map<String, Object> addValMap) {
        HashMap<String, Object> returnMap = new HashMap<>();
        HashMap<String, Object> typeMap = new HashMap<>();

        try {
            Class<?> type = object.getClass();
            // 在 Java Bean上进行内省,了解其所有属性、公开的方法和事件
            BeanInfo beanInfo = Introspector.getBeanInfo(type);
            // 获得 beans PropertyDescriptor
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (int i = 0; i < propertyDescriptors.length; i++) {
                PropertyDescriptor descriptor = propertyDescriptors[i];
                // 获得所有对象属性值得名字
                String propertyName = descriptor.getName();
                if (!"class".equals(propertyName)) {
                    // 设置应用于读取属性值的方法
                    Method readMethod = descriptor.getReadMethod();
                    // 处理代理实例上的方法调用并返回结果
                    Object result = readMethod.invoke(object);
                    returnMap.put(propertyName, result);
                    typeMap.put(propertyName, descriptor.getPropertyType());
                }
            }

            returnMap.putAll(addValMap);
            typeMap.putAll(addMap);
            // map转换成实体对象
            DynamicBean bean = new DynamicBean(typeMap);
            // 赋值
            Set keys = typeMap.keySet();
            for (Iterator it = keys.iterator(); it.hasNext(); ) {
                String key = (String) it.next();
                bean.setValue(key, returnMap.get(key));
            }
            return bean.getObject();
        } catch (Exception e) {
            log.warn("动态添加参数错误:{}", e);
            return object;
        }
    }


    private static class DynamicBean {
        // 动态生成的类
        private Object object = null;
        // 存放属性名称以及属性的类型
        private BeanMap beanMap = null;

        public DynamicBean() {
            super();
        }

        public DynamicBean(Map propertyMap) {
            this.object = generateBean(propertyMap);
            this.beanMap = BeanMap.create(this.object);
        }

        /**
         * 生成Bean
         *
         * @param propertyMap
         * @return
         */
        private Object generateBean(Map propertyMap) {
            BeanGenerator generator = new BeanGenerator();
            Set keySet = propertyMap.keySet();
            for (Iterator i = keySet.iterator(); i.hasNext(); ) {
                String key = (String) i.next();
                generator.addProperty(key, (Class) propertyMap.get(key));
            }
            return generator.create();
        }

        /**
         * 给bean属性赋值
         *
         * @param property 属性名
         * @param value    值
         */
        public void setValue(Object property, Object value) {
            beanMap.put(property, value);
        }

        /**
         * 通过属性名得到属性值
         *
         * @param property 属性名
         * @return 值
         */
        public Object getValue(String property) {
            return beanMap.get(property);
        }

        /**
         * 得到该实体bean对象
         *
         * @return
         */
        public Object getObject() {
            return this.object;
        }
    }

    /**
     * 获取对象中的所有属性名与属性值
     *
     * @param object
     * @return
     * @throws
     */
    public static Map<String, Class> getAllPropertyType(Object object) {
        Map<String, Class> map = new HashMap<String, Class>();
        try {
            Field[] fields = object.getClass().getDeclaredFields();
            for (int index = 0; index < fields.length; index++) {
                Field field = fields[index];
                String propertyName = field.getName();
                Class<?> propertyType = Class.forName(field.getGenericType().getTypeName());
                map.put(propertyName, propertyType);
            }
            return map;
        } catch (ClassNotFoundException e) {
            log.error(String.format("从对象%s获取所有属性失败", object));
        }
        return map;
    }

    /**
     * 获取对象中的所有属性名与属性值
     *
     * @param object
     * @return
     * @throws
     */
    public static Map<String, Object> getAllPropertyValue(Object object) {
        Map<String, Object> map = new HashMap<>();
        Class<?> aClass = object.getClass();
        if (aClass.equals(HashMap.class) || aClass.equals(JSONObject.class)) {
            return JSONObject.parseObject(JSONObject.toJSONString(object), new TypeReference<Map<String, Object>>(){});
        } else {
            Field[] fields = object.getClass().getDeclaredFields();
            for (int index = 0; index < fields.length; index++) {
                Field field = fields[index];
                String propertyName = field.getName();
                if (propertyName.contains("$cglib_prop_")) {
                    Matcher matcher = COMPILE.matcher(propertyName);
                    if (matcher.find()) {
                        propertyName = matcher.group(2);
                    }
                }
                Object propertyValue = getPropertyValueByName(object, propertyName);
                map.put(propertyName, propertyValue);
            }
            return map;
        }
    }

    /**
     * 根据属性名获取对象中的属性值
     *
     * @param propertyName
     * @param object
     * @return
     */
    public static Object getPropertyValueByName(Object object, String propertyName) {
        String methodName = "get" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
        Object value = null;
        try {
            Method method = object.getClass().getMethod(methodName, new Class[]{});
            value = method.invoke(object, new Object[]{});
        } catch (Exception e) {
            log.error(String.format("从对象%s获取%s的=属性值失败", object, propertyName));
        }
        return value;
    }
}


// 测试
public class Test {

    @Data
    public static class Order {
        private Integer id;
        private String name;
    }

    public static void main(String[] args) throws Exception {
        Order order = new Order();
        order.setId(1);
        order.setName("test");

        try {
            HashMap addMap = new HashMap();
            HashMap addValMap = new HashMap();
            addMap.put("badge", Class.forName("java.lang.Boolean"));
            addValMap.put("badge", false);

            Object obj2= DynamicAddParamUtil.dynamicClass(order,addMap,addValMap);
            String param = JSON.toJSONString(obj2);
            System.out.println(param);

            Map<String, Object> value = DynamicAddParamUtil.getAllPropertyValue(obj2);
            System.out.println(value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}













 

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用CGLIB动态添加属性时,你可以通过以下步骤实现: 1. 创建一个需要被增强的类,该类无法直接添加属性。 2. 创建一个类来扩展`net.sf.cglib.proxy.MethodInterceptor`接口,用于拦截方法调用并进行增强操作。 3. 使用CGLIB库生成代理对象,将该代理对象作为原始对象的子类返回。 4. 在拦截器中,可以使用`net.sf.cglib.beans.BeanGenerator`来动态添加属性。 下面是一个简单示例代码: ```java import net.sf.cglib.beans.BeanGenerator; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; import java.lang.reflect.Method; public class DynamicPropertyExample { public static class MyBean { public void printName() { System.out.println("Original method"); } } public static class PropertyInterceptor implements MethodInterceptor { private Object target; public PropertyInterceptor(Object target) { this.target = target; } public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { if (method.getName().equals("getProperty")) { // 添加动态属性逻辑 // 实际应用中可根据需要进行属性的添加和获取 return "Dynamic Property Value"; } return method.invoke(target, args); } } public static Object createDynamicPropertyObject() { BeanGenerator generator = new BeanGenerator(); generator.addProperty("propertyName", String.class); // 动态添加名为propertyName的String类型属性 return generator.create(); } public static void main(String[] args) { MyBean bean = (MyBean) createDynamicPropertyObject(); Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(MyBean.class); enhancer.setCallback(new PropertyInterceptor(bean)); MyBean proxyBean = (MyBean) enhancer.create(); proxyBean.printName(); // 调用原始方法 System.out.println(proxyBean.getProperty()); // 动态获取属性 } } ``` 在这个示例中,我们使用`BeanGenerator`来动态添加一个名为`propertyName`的String类型属性。然后,我们使用`Enhancer`来创建代理对象,并将代理对象传递给自定义的拦截器`PropertyInterceptor`。在`PropertyInterceptor`中,我们拦截了`getProperty`方法的调用,并返回动态添加的属性。 请注意,这只是一个简单的示例代码,实际情况下你可能需要根据具体需求进行更复杂的操作。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值