Java 类动态添加属性字段的操作

说明:

做项目中遇到一种场景,需要根据查询时间段, 获取时间段中中每个月份对应的金额(费用统计)。

如截图中的两列

因为列是动态的, 首先想到的就是后天拼接JSON格式字符串, 然后返回到前台, 组装表头及内容。

但是当前系统中easyUI版本为1.2,并不支持 data属性(官方从1.3.2开始支持)。所以只能返回list<T> 格式。

网上一搜相关代码很多, 看客可以自己搜索一下。 我这里记录一下我当时使用场景及用法,已备以后使用。

1.需要引用cglib jar包, 我用的版本是2.2

2.建一个实体对象 DynamicBean.java 。主要用来处理对象。

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

 /**
  * @param propertyMap
  * @return
  */
 private Object generateBean(Map propertyMap) {
  BeanGenerator generator = new BeanGenerator();
  Set keySet = propertyMap.keySet();
  for (Iterator<String> 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);
 }

 /**
  * 返回新生成的对象
  * @return
  */
 public Object getObject() {
  return this.object;
 }
}

3. 原来对象, 及需要拼接到对象中的属性字段集合处理方法。

/**
*参数说明:
* object : 查询结果数组中对象。
* moneyMap : 为对象对应所有月份数据集合
* 解释:已经查询出一组账单对象集合List<Bill> , 而moneyMap为对象中的一个属性
* Map<String,Bigdecimal>, 存放了月份及金额
*/
private Object dynamicClass(Object object, Map<String, BigDecimal> moneyMap) throws Exception {
  // 字段 - 值 集合
  HashMap<String, Object> returnMap = new HashMap<String, Object>();
  // 字段 - 字段类型 集合
  HashMap<String, Object> typeMap = new HashMap<String, Object>();
  // 获取传入类
  Class<? extends Object> type = object.getClass();
  BeanInfo beanInfo = Introspector.getBeanInfo(type);
  PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
  // 获取对象中已存在的数据
  for (int i = 0; i < propertyDescriptors.length; i++) {
   PropertyDescriptor descriptor = propertyDescriptors[i];
   String propertyName = descriptor.getName();
   if (!propertyName.equals("class") && !propertyName.equals("monthMap")) {
    Method readMethod = descriptor.getReadMethod();
    Object result = readMethod.invoke(object, new Object[0]);
    if (result != null) {
     returnMap.put(propertyName, result);
    } else {
     String propertyType = descriptor.getPropertyType().toString();
     if (propertyType.contains("java.math.BigDecimal")) {
      returnMap.put(propertyName, new BigDecimal(0));
     } else {
      returnMap.put(propertyName, "");
     }
    }
    typeMap.put(propertyName, descriptor.getPropertyType());
   }
  }
  // 获取月份数据, 变为字段属性
  Set<String> monthKeys = moneyMap.keySet();
  for (Iterator<String> it = monthKeys.iterator(); it.hasNext();) {
   String key = (String) it.next();
   // 字段类型
   typeMap.put(key, Class.forName("java.math.BigDecimal"));
   // 字段对应值
   returnMap.put(key, moneyMap.get(key));
  }
  // map转换成实体对象
  DynamicBean bean = new DynamicBean(typeMap);
  // 赋值
  Set<String> keys = typeMap.keySet();
  for (Iterator<String> it = keys.iterator(); it.hasNext();) {
   String key = (String) it.next();
   bean.setValue(key, returnMap.get(key));
  }
  Object obj = bean.getObject();
  return obj;
 }

做笔记使用, 说不定以后还会用到。

补充:java动态的生成类的属性、并赋值

1、springboot项目中,在build.gradle中,配置jar包

compile("commons-beanutils:commons-beanutils:1.9.3")
compile("cglib:cglib-nodep:3.2.4")

2、创建DynamicBean

import java.util.Map;
import net.sf.cglib.beans.BeanGenerator;
import net.sf.cglib.beans.BeanMap;
public class DynamicBean {

 /**
  * 目标对象
  */
 private Object target;
 /**
  * 属性集合
  */
 private BeanMap beanMap;

 public DynamicBean(Class superclass, Map<String, Class> propertyMap){
  this.target = generateBean(superclass, propertyMap);
  this.beanMap = BeanMap.create(this.target);
 }

 /**
  * bean 添加属性和值
  *
  * @param property
  * @param value
  */
 public void setValue(String property, Object value) {
  beanMap.put(property, value);
 }

 /**
  * 获取属性值
  *
  * @param property
  * @return
  */
 public Object getValue(String property) {
  return beanMap.get(property);
 }

 /**
  * 获取对象
  *
  * @return
  */
 public Object getTarget() {
  return this.target;
 }

 /**
  * 根据属性生成对象
  *
  * @param superclass
  * @param propertyMap
  * @return
  */
 private Object generateBean(Class superclass, Map<String, Class> propertyMap) {
  BeanGenerator generator = new BeanGenerator();
  if (null != superclass) {
   generator.setSuperclass(superclass);
  }
  BeanGenerator.addProperties(generator, propertyMap);
  return generator.create();
 }
}

3、创建ReflecUtil转换的工具类

import java.beans.PropertyDescriptor;
import java.util.HashMap;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.commons.beanutils.PropertyUtilsBean;
import com.sunxung.factoring.entity.DynamicBean;
import com.sunxung.factoring.entity.attendanceManagement.AttendanceVo;

/**
 * @className:ReflectUtil
 * @description:动态生成类的属性、并且赋值
 * @date:2018年4月3日 下午2:33:10
 */
public class ReflectUtil {

 static Logger logger = LogManager.getLogger(ReflectUtil.class);

 @SuppressWarnings("rawtypes")
 public static Object getTarget(Object dest, Map<String, Object> addProperties) {
  PropertyUtilsBean propertyUtilsBean = new PropertyUtilsBean();
  PropertyDescriptor[] descriptors = propertyUtilsBean.getPropertyDescriptors(dest);
  Map<String, Class> propertyMap = new HashMap<>();
  for (PropertyDescriptor d : descriptors) {
   if (!"class".equalsIgnoreCase(d.getName())) {
    propertyMap.put(d.getName(), d.getPropertyType());
   }
  }
  // add extra properties
  addProperties.forEach((k, v) -> propertyMap.put(k, v.getClass()));
  // new dynamic bean
  DynamicBean dynamicBean = new DynamicBean(dest.getClass(), propertyMap);
  // add old value
  propertyMap.forEach((k, v) -> {
   try {
    // filter extra properties
    if (!addProperties.containsKey(k)) {
     dynamicBean.setValue(k, propertyUtilsBean.getNestedProperty(dest, k));
    }
   } catch (Exception e) {
    logger.error(e.getMessage(), e);
   }
  });
  // add extra value
  addProperties.forEach((k, v) -> {
   try {
    dynamicBean.setValue(k, v);
   } catch (Exception e) {
    logger.error(e.getMessage(), e);
   }
  });
  Object target = dynamicBean.getTarget();
  return target;
 }

 public static void main(String[] args) {
  AttendanceVo entity = new AttendanceVo();
  Map<String, Object> addProperties = new HashMap<>();
  addProperties.put("day31", "你好");
  AttendanceVo newVo = (AttendanceVo) getTarget(entity, addProperties);
  System.out.println(newVo.getDay0());
 }
}

4、在项目中动态生成属性并且赋值的使用

private AttendanceVo autoDetailNew(SearchAttendanceVo search, AttendanceVo att) {
  search.setDingdingUserId(att.getDingdingUserId());
  List<Attendance> detailList = attendanceMapper.findDetailList(search);
  Map<String, Object> addProperties = new HashMap<>();
  for (Attendance attendance : detailList) {
   addProperties.put("day" + DateUtil.getDayStringFormatYMD(attendance.getAttendanceDate()),
     attendance.getRemark());
  }
  AttendanceVo newVo = (AttendanceVo) ReflectUtil.getTarget(att, addProperties);
  return newVo;
 }

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • Java如何读取配置文件并赋值静态变量

    应用场景 项目开发中某个功能需要抽取成方法写成一个工具类,提供给别人使用.写过工具类的人都知道,工具类中的方法一般都是静态方法,可以直接使用类名点方法名调用, 使用很方便,比如判断某个对象是否为null的方式Objects.equals().由于我写的这个工具类中需要读取配置文件中的内容,可是常规方式注入成员变量时都不是静态的,不 能直接调用,比如这种方式: @Data @Component public class GBaseApiConfig { @Value("${gbase.api.pr

  • SpringBoot中属性赋值操作的实现

    说明:当程序中出现频繁变化的数据时,如果采用认为的方式进行修改并且编译打包则会导致代码的耦合性较高,不便于维护!所以能否为属性动态赋值? 属性固定值 //动态获取ip和端口数据 /** * @responseBody * 注解作用: * 1.将对象转化成Json格式, * 2.如果返回值是String类型,则返回字符串本身 * 3.一般客户端发起ajax请求时,采用该注解返回数据,将不会执行视图解析器操作 */ @RestController public class RedisControll

  • Java 通过反射给实体类赋值操作

    表单提交这个方法是挺方便的,但在java来说就显得有些麻烦了, 怎么个麻烦呢,就是当你字段多的时候,你就得一个一个的获取其对应的值,这样代码量就多了起来,其代码量不说,维护也是一个问题. 所以就有了这样一个类,只需把request和实体类对象传进去就行了, 这样就会得到一个有值的实体类对象 下面是代码示例 import java.lang.reflect.Field; import java.lang.reflect.Method; import java.sql.Date; import ja

  • Java 类动态添加属性字段的操作

    说明: 做项目中遇到一种场景,需要根据查询时间段, 获取时间段中中每个月份对应的金额(费用统计). 如截图中的两列 因为列是动态的, 首先想到的就是后天拼接JSON格式字符串, 然后返回到前台, 组装表头及内容. 但是当前系统中easyUI版本为1.2,并不支持 data属性(官方从1.3.2开始支持).所以只能返回list<T> 格式. 网上一搜相关代码很多, 看客可以自己搜索一下. 我这里记录一下我当时使用场景及用法,已备以后使用. 1.需要引用cglib jar包, 我用的版本是2.2

  • Java为实体类动态添加属性的方法详解

    目录 添加依赖 代码 测试 可以给已有实体类动态的添加字段并返回新的实体对象,不影响原来的实体对象结构. 添加依赖 <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <dependency> <groupId>commons

  • Python实现动态添加属性和方法操作示例

    本文实例讲述了Python实现动态添加属性和方法操作.分享给大家供大家参考,具体如下: # -*- coding:utf-8 -*- #!python3 class Person(): def __init__(self, name, age): self.name = name self.age = age p1 = Person('ff', '28') print(p1.name, p1.age) # 给实例对象动态添加sex属性 p1.sex = 'female' print(p1.sex

  • Java cglib为实体类(javabean)动态添加属性方式

    1.应用场景 之前对接三方平台遇到一个参数名称是变化的,然后我就想到了动态javabean怎么生成,其实是我想多了,用个map就轻易解决了,但还是记录下动态属性添加的实现吧. 2.引入依赖 <!--使用cglib 为javabean动态添加属性--> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId>

  • Python实现动态给类和对象添加属性和方法操作示例

    本文实例讲述了Python实现动态给类和对象添加属性和方法操作.分享给大家供大家参考,具体如下: 动态给类和对象添加属性 定义一个Person类 class Person(object): def __init__(self, name): self.name = name 给对象添加属性 # 创建2个Person,分别为p1,p2 p1 = Person('amy') print(p1.name) p1.age = 10 # 给p1对象添加属性 print(p1.age) # 输出10 p2

  • Javascript 创建类并动态添加属性及方法的简单实现

    JavaScript 是一种很强的面向对象的语言,支持创建实例之后再添加属性和方法,虽然是小技巧,用的时候容易忘记,今天写了一个很小的例子,记录在这里,仅供参考. function MyClass() { //This function is same as a constructer alert("New Object Created"); } //Creating Object var MyObject = new MyClass (); NewObject.prototype =

  • 详解Java类动态加载和热替换

    前言 最近,遇到了两个和Java类的加载和卸载相关的问题: 1) 是一道关于Java的判断题:一个类被首次加载后,会长期留驻JVM,直到JVM退出.这个说法,是不是正确的? 2) 在开发的一个集成平台中,需要集成类似接口的多种工具,并且工具可能会有新增,同时在不同的环境部署会有裁剪(例如对外提供服务的应用,不能提供特定的采购的工具),如何才能更好地实现? 针对上面的第2点,我们采用Java插件化开发实现.上面的两个问题,都和Java的类加载和热替换机制有关. 1. Java的类加载器和双亲委派模

  • JS实现给对象动态添加属性的方法

    本文实例讲述了JS实现给对象动态添加属性的方法.分享给大家供大家参考,具体如下: 在工作用要用到给jd对象动态添加属性的要求,在网上找到了一种解决方式,实例如下: 1.demo var aa="maker"; var bb=123; var lists={}; eval("lists."+aa+"="+bb); eval('('+"lists."+aa+"="+bb+')'); console.log(li

  • 遍历json 对象的属性并且动态添加属性的实现

    昨天因为公司的一个需求,所以就研究了一下json对象的属性的遍历和动态修改: var person= { name: 'zhangsan', pass: '123' , 'sni.ni' : 'sss', hello:function (){ for(var i=0;i<arguments.length;i++){ //在不知参数个数情况下可通过for循环遍历 // arguments这个是js 默认提供 alert("arr["+i+"]="+argumen

  • vue给对象动态添加属性和值的实例

    一.背景 介绍:在vue中请求接口中,一个请求方法可能对应后台两个请求接口,所以请求参数就会有所不同.需要我们先设置共同的参数,然后根据条件动态添加参数属性. 二.案例 let that = this; let params = { "type":that.addQueTable.type, "discussTitle":that.addQueTable.discussTitle, }; // 区分普通题库还是模考题库 let addQuestionApi = ''

随机推荐