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

这个Java代码实现了一个工具类`DynamicAddParamUtil`,用于动态地为对象添加属性和值。它利用了反射、CGlib库以及FastJSON进行操作。工具类包括获取对象的所有属性名与属性值、动态生成Bean并赋值等功能,适用于需要动态扩展对象属性的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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();
        }
    }
}













 

### 使用 JDK 动态代理配置 Spring Boot 应用 在 Spring Boot 中,默认情况下会优先使用 CGLIB 进行代理创建,但如果目标类实现了接口,则可以强制使用 JDK 动态代理。为了实现这一点,在 `application.properties` 或者 `application.yml` 文件中设置相应的属性[^3]。 对于启用 JDK 动态代理,可以在 `application.properties` 添加如下配置: ```properties spring.aop.proxy-target-class=false ``` 这表明 AOP 的切面将会通过标准 Java 接口来应用而不是依赖于具体的类实例。当此选项设为 false 时,意味着将采用基于接口的 JDK Proxy 方式来进行方法拦截;而 true 则表示使用 CGLIB 创建子类形式的代理对象[^1]。 下面是一个简单的例子展示如何定义一个服务并为其添加日志记录功能作为横切关注点: #### 定义业务逻辑接口和服务实现 ```java public interface MyService { void doSomething(); } @Service public class MyServiceImpl implements MyService { @Override public void doSomething() { System.out.println("Doing something..."); } } ``` #### 创建 Aspect 来处理横切关注点 ```java @Aspect @Component public class LoggingAspect { private static final Logger logger = LoggerFactory.getLogger(LoggingAspect.class); @Around("execution(* com.example..*.*(..))") public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable { long start = System.currentTimeMillis(); try { return joinPoint.proceed(); } finally { long executionTime = System.currentTimeMillis() - start; logger.info("{} executed in {} ms", joinPoint, executionTime); } } } ``` 上述代码片段展示了如何利用 Spring AOP 和 JDK 动态代理机制为应用程序中的某些操作增加额外的行为——在这个案例里就是打印执行时间的日志信息。需要注意的是,只有当被代理的对象实现了至少一个接口的时候才会生效,因为这是 JDK 动态代理的工作原理所决定的[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值