程序员子龙(Java面试 + Java学习) 程序员子龙(Java面试 + Java学习)
首页
学习指南
工具
开源项目
技术书籍

程序员子龙

Java 开发从业者
首页
学习指南
工具
开源项目
技术书籍
  • 基础

  • JVM

  • Spring

    • 动态代理-CGLIB
    • Hibernate Validator 参数校验优雅实战
    • Jackson序列化json时null转成0或空串
    • 别自己瞎写工具类了!SpringBoot中自带工具类,开发效率增加一倍
    • Spring @Autowired Map
    • SpringBoot 缓存之 @Cacheable 详细介绍与失效时间TTL
    • Spring Security 入门
    • Spring Security原理
    • Spring项目整合MybatisPlus出现org.mybatis.logging.LoggerFactory Not Found 异常
    • Spring在代码中获取bean
    • 别再乱写了,Controller 层代码这样写才足够规范!
    • 非静态变量给静态变量赋值
    • 过滤器与拦截器区别、使用场景
    • 接口重试机制 Spring-Retry
    • 利用cglib动态创建对象或在原对象新增属性
    • 聊聊spring事务失效的场景
    • Spring Event 事件解耦
    • 最全的Spring依赖注入方式
    • Spring初始化之ApplicationRunner、InitializingBean、@PostConstruct 使用详解
    • 为啥不建议用 BeanUtils.copyProperties 拷贝数据
  • 并发编程

  • Mybatis

  • 网络编程

  • 数据库

  • 缓存

  • 设计模式

  • 分布式

  • 高并发

  • SpringBoot

  • SpringCloudAlibaba

  • Nginx

  • 面试

  • 生产问题

  • 系统设计

  • 消息中间件

  • Java
  • Spring
程序员子龙
2024-01-29

利用cglib动态创建对象或在原对象新增属性

引入依赖

  <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib-nodep</artifactId>
      <version>3.2.4</version>
  </dependency>

1
2
3
4
5
6

定义实体

@Data
public class User {

    private String name;

    private Integer age;
}
1
2
3
4
5
6
7

直接上代码


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

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;

@Slf4j
public class DynamicObject {
    
    private Object object;    //对象
    
    private BeanMap beanMap;    //对象的属性
    
    private BeanGenerator beanGenerator;    //对象生成器
    
    private Map<String, Class> allProperty;    //对象的<属性名, 属性名对应的类型>

    public DynamicObject() {
    }
    

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

    private void setValue(Object object, Map<String, Class> property){
        for(String propertyName : property.keySet()){
            if(allProperty.containsKey(propertyName)){
                Object propertyValue = getPropertyValueByName(object, propertyName);
                this.setValue(propertyName, propertyValue);
            }
        }
    }
    
    private void setValue(Map<String, Object> propertyValue){
        for(Map.Entry<String, Object> entry : propertyValue.entrySet()){
            this.setValue(entry.getKey(), entry.getValue());
        }
    }
    
    /**通过属性名获取属性值
     * 
     * @param property
     * @return
     */
    public Object getValue(String property){
        return beanMap.get(property);
    }
    
    /**获取该bean的实体
     * 
     * @return
     */
    public Object getObject(){
        return this.object;
    }
    
    public Map<String, Class> getAllProperty() {
        return allProperty;
    }


    private Object generateObject(Map propertyMap){
        if(null == beanGenerator){
            beanGenerator = new BeanGenerator();
        }

        Set keySet = propertyMap.keySet();
        for(Iterator i = keySet.iterator(); i.hasNext();){
            String key = (String) i.next();
            beanGenerator.addProperty(key, (Class)propertyMap.get(key));
        }
        return beanGenerator.create();
    }
    
    /**添加属性名与属性值
     * 
     * @param propertyType
     * @param propertyValue
     */
    private void addProperty(Map propertyType, Map propertyValue){
        if(null == propertyType){
            throw new RuntimeException("动态添加属性失败!");
        }
        Object oldObject = object;
        object = generateObject(propertyType);
        beanMap = BeanMap.create(object);
        
        if(null != oldObject){
            setValue(oldObject, allProperty);
        }
        
        setValue(propertyValue);
        if(null == allProperty){
            allProperty = propertyType;
        }else{
            allProperty.putAll(propertyType);
        }
    }
    
    /**获取对象中的所有属性名与属性值
     * 
     * @param object
     * @return
     * @throws ClassNotFoundException 
     */
    public Map<String, Class> getAllPropertyType(Object object) throws ClassNotFoundException{
        Map<String, Class> map = new HashMap<String, Class>();
        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;
    }

    /**获取对象中的所有属性名与属性值
     * 
     * @param object
     * @return
     * @throws ClassNotFoundException 
     */
    public Map<String, Object> getAllPropertyValue(Object object) throws ClassNotFoundException{
        Map<String, Object> map = new HashMap<String, Object>();
        Field[] fields = object.getClass().getDeclaredFields();
        for(int index = 0; index < fields.length; index ++){
            Field field = fields[index];
            String propertyName = field.getName();
            Object propertyValue = getPropertyValueByName(object, propertyName);
            map.put(propertyName, propertyValue);
        }
        return map;
    }

    /**根据属性名获取对象中的属性值
     * 
     * @param propertyName
     * @param object
     * @return
     */
    private 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 static void main(String[] args) throws ClassNotFoundException {

        User user = new User();
        user.setName("张三");
        user.setAge(20);

        DynamicObject dynamicBean = new DynamicObject();

        //1、在原来的对象新增属性
        Map<String, Class> allPropertyType = dynamicBean.getAllPropertyType(user);
        Map<String, Object> allPropertyValue = dynamicBean.getAllPropertyValue(user);
        allPropertyType.put("phone", Class.forName("java.lang.String"));
        allPropertyValue.put("phone", "1321111111");
        dynamicBean.addProperty(allPropertyType, allPropertyValue);

        System.out.println(JSON.toJSON(dynamicBean.getObject()));
        
        //2、动态创建一个新对象
        Map<String, Class> newPropertyType = new HashMap<>();
        Map<String, Object> newPropertyValue = new HashMap<>();
        newPropertyType.put("address", Class.forName("java.lang.String"));
        newPropertyValue.put("address", "地址地址");

        dynamicBean.addProperty(newPropertyType, newPropertyValue);

        Object entity = dynamicBean.getObject();

        System.out.println(JSONObject.toJSONString(entity));
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198

{"name":"张三","phone":"1321111111","age":20} {"address":"地址地址","age":20,"name":"张三","phone":"1321111111"}

上次更新: 2024/01/30, 15:08:57
接口重试机制 Spring-Retry
聊聊spring事务失效的场景

← 接口重试机制 Spring-Retry 聊聊spring事务失效的场景→

最近更新
01
一个注解,优雅的实现接口幂等性
11-17
02
MySQL事务(超详细!!!)
10-14
03
阿里二面:Kafka中如何保证消息的顺序性?这周被问到两次了
10-09
更多文章>
Theme by Vdoing | Copyright © 2024-2024

    辽ICP备2023001503号-2

  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式