java动态生成对象和属性

最近项目中大量使用了流程,流程框架采用的是activity,客户要求把表单数据和对应的流程审批数据导出为pdf,简单的做法就是扩展表单的类,把每一个流程节点作为一个属性添加到类,但是有个问题是:流程不确定,后续可能会修改,导致流程节点无法写死到类上。

然后想到可以利用cglib的动态生成类和属性的方法,动态的把流程节点作为属性添加到类,同时为了方便维护,使用自定义注解和aop统一进行处理。自定义注解和aop的使用可参考SpringAOP+自定义注解实现日志功能,这里不详细说了,下面说下实现思路和实现代码,代码只粘贴了主要部分。

在要增加流程节点Controller的方法上添加自定义的注解,当收到请求时进入AOP,配合注解获取要处理的对象和其流程id的值,通过流程id查询到包含流程节点数据的map,把对象和map使用cglib的动态生成类和属性的方法生成对象并返回。

Annotation:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RelationFiled {

	/**
	 * 视图模型对象中数据的key
	 * @return
	 */
	String attributeName();
	/**
	 * 数据对象的属性(流程实例id)
	 * @return
	 */
	String propertyName() default "procInsId";
	/**
	 * 数据对象要添加的字段名称
	 * @return
	 */
	String[] fields() default {};
	
}

Controller:

@RelationFiled(attributeName="process",fields= {"startAudit","startAuditName"})
@RequiresPermissions("xx:xxx:exportPdf")
@RequestMapping(value = "exportPdf")
public String exportPdf(Process process, Model model) {
	model.addAttribute("process", process);
	return "modules/gz/process/exportPdf";
}

AOP:

@Around("actPointcut()")
public Object doAround(ProceedingJoinPoint pjp){
	
	Object obj = null;
	try {
		//执行切入点方法
		obj = pjp.proceed();
		//获取执行方法
		MethodSignature ms = (MethodSignature)pjp.getSignature();
		Method method = pjp.getTarget().getClass().getDeclaredMethod(ms.getName(), ms.getParameterTypes());
		//获取执行方法RelationFiled注解
		RelationFiled rf = method.getAnnotation(RelationFiled.class);
		//获取方法参数
		Object[] args = pjp.getArgs();
		Object object = null;
		ModelMap model = null;//根据自己项目实际情况而定,比如使用的是ModelAndView这里就是ModelAndView
        for (Object arg : args) {
            if (arg instanceof Model){
            	model = (ModelMap) arg;
            	object = model.get(rf.attributeName());//通过rf.attributeName()自定义注解参数值获取要生成属性的对象
            	break;
            }
        }
        //根据反射获取流程id
		Field field = object.getClass().getDeclaredField(rf.propertyName());
		field.setAccessible(true);
		Object procInsId = field.get(object);
		//根据流程id获取流程数据
		Map<String, Object> map = actTaskService.getMap(procInsId == null?null:procInsId.toString());
		//添加指定生成的属性到map,model中如有指定属性的数据可同时进行处理
		String[] fields = rf.fields();
		for(String f : fields) {
			//不覆盖存在的属性
			if(!map.containsKey(f)) {
				map.put(f, "");
			}
		}
		//生成属性并返回
		model.addAttribute(mi.attributeName(), PropertyUtils.generate(object, map));
	} catch (Throwable e) {
		e.printStackTrace();
	}
	return obj;
}

PropertyUtils:

package com.xx.xx.utils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import org.springframework.cglib.beans.BeanGenerator;
import org.springframework.cglib.beans.BeanMap;

public class PropertyUtils {
	private static final class DynamicBean {
		private Object object;
        private BeanMap beanMap;
		//创建对象和属性map
        private DynamicBean(Class<?> superclass, Map<String, Class<?>> propertyMap) {
            this.object = generateBean(superclass, propertyMap);
            this.beanMap = BeanMap.create(this.object);
        }
		//为对象属性赋值
        private void setValue(String property, Object value) {
            beanMap.put(property, value);
        }

        private Object getObject() {
            return this.object;
        }
		//创建对象
        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();
        }
	}
	/**
	 * 动态创建对象
	 * @param valueMap 动态对象的属性和值
	 * @return
	 */
	public static Object generate(Map<String, Object> valueMap) {
		return generate(null, valueMap);
	}
	/**
	 * 动态创建对象,可继承其它对象的属性
	 * @param object 被继承属性的对象
	 * @param valueMap 动态对象的属性和值
	 * @return
	 */
	public static Object generate(Object object, Map<String, Object> valueMap) {
		Map<String,Class<?>> fieldMap = new HashMap<String, Class<?>>();//要创建的属性
		valueMap.forEach((k, v) -> {
			if(k == null) {
				
			}else if(v == null) {
				fieldMap.put(k, Object.class);
			}else {
				fieldMap.put(k, v.getClass());
			}
        });
		Class<?> clazz = null;
		Class<?> superclass = null;
		if(object != null) {
			clazz = object.getClass();
			superclass = clazz;
		}
		//获取对象属性的值并保存到valueMap
		while (clazz != null) {
			for (Field field : clazz.getDeclaredFields()) {
				try {
					field.setAccessible(true);
					valueMap.put(field.getName(), field.get(object));
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
            clazz = clazz.getSuperclass();
        }
        //生成动态对象
		DynamicBean dynamicBean = new DynamicBean(superclass,fieldMap);
		//为动态对象属性赋值
		valueMap.forEach((k, v) -> {
        	dynamicBean.setValue(k, v);
        });
		return dynamicBean.getObject();
	}
}

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值