利用动态代理实现类中属性的动态生成。
使用场景:当不确定返回类中字段个数时,可使用动态生成属性个数实现需求。
注意:由于CGLib由于是采用动态创建子类的方法,对于final方法,无法进行代理。
引入依赖
<dependency> <groupId>cglibgroupId> <artifactId>cglib-nodepartifactId> <version>3.2.5version>dependency> <dependency> <groupId>commons-beanutilsgroupId> <artifactId>commons-beanutilsartifactId> <version>1.9.3version>dependency><dependency> <groupId>com.google.guavagroupId> <artifactId>guavaartifactId> <version>14.0version>dependency>
2、动态Bean
public class DynamicBean { private Object target; private BeanMap beanMap; public DynamicBean(Class superclass, Map propertyMap) { this.target = generateBean(superclass, propertyMap); this.beanMap = BeanMap.create(this.target); } public void setValue(String property, Object value) { beanMap.put(property, value); } public Object getValue(String property) { return beanMap.get(property); } public Object getTarget() { return this.target; } /** * 根据属性生成对象 * */ private Object generateBean(Class superclass, Map propertyMap) { BeanGenerator generator = new BeanGenerator(); if (null != superclass) { generator.setSuperclass(superclass); } BeanGenerator.addProperties(generator, propertyMap); return generator.create(); }}
3、动态工具类 ReflectUtil
public class ReflectUtil { private static Logger logger = LoggerFactory.getLogger(ReflectUtil.class); public static Object getObject(Object dest, Map<String, Object> addProperties) { PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean(); PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest); Map<String, Class> propertyMap = Maps.newHashMap(); for (PropertyDescriptor d : descriptors) { if (!"class".equalsIgnoreCase(d.getName())) { propertyMap.put(d.getName(), d.getPropertyType()); } } addProperties.forEach((k, v) -> { String sclass = v.getClass().toString(); if(sclass.equals("class java.util.Date")) {//对日期进行处理 propertyMap.put(k, Long.class); }else { propertyMap.put(k, v.getClass()); } }); DynamicBean dynamicBean = new DynamicBean(dest.getClass(), propertyMap); propertyMap.forEach((k, v) -> { try { if (!addProperties.containsKey(k)) { dynamicBean.setValue(k, propertyUtilsBean.getNestedProperty(dest, k)); } } catch (Exception e) { logger.error("动态添加字段出错", e); } }); addProperties.forEach((k, v) -> { try { String sclass = v.getClass().toString(); if(sclass.equals("class java.util.Date")) {//动态添加的字段为date类型需要进行处理 Date date = (Date) v; dynamicBean.setValue(k, date.getTime()); }else { dynamicBean.setValue(k, v); } } catch (Exception e) { logger.error("动态添加字段值出错", e); } }); Object obj = dynamicBean.getTarget(); return obj; }}
4、测试 TEST
//测试类public class User { String userName; Integer userAge;}
@GetMapping("cglib")public ResultData cglib (){ User user = new User(); Map<String,Object> propertiesMap = new HashMap<String,Object>(); Map<String,Object> hashMap = new HashMap<String,Object>(); for (int i = 0; i < 5; i++) { propertiesMap.put("activity"+i, "活动"+i); } Object obj = ReflectUtil.getObject(user, propertiesMap); return new ResultData().setData(obj);}
返回结果
遇到情况:利用 System.out.println(); 打印结果不会显示,只能在调用返回结果时,才会显示动态添加了类属性。