在很多的业务系统中,erp,crm 系统中,有许多的对象信息都是拆开来的,例如一个商品,那可能他的商品名称,商品等主要信息放在一个表(衍生出来一个对象),他的附属信息(商品图片,规格,价格等)可能会在其他的多个表(对象)中,这个时候一般我们想到的操作是:
1. 将主要的对象查询出来
2. 利用主要对象和其他附属信息的关联字段来查询主对象关联的附属信息对象列表
3. 将查询到的附属信息和主对象关联的字段作为 key,附属信息作为 value 组装 map
4. 组装一个 VO 包装所有信息,操作:
for( 主对象 : 主对象列表){
新建 VO,将主对像信息填充进去;
根据主对像关联附属信息的字段在 map 中获取附属信息拿到附属信息对象
将附属信息填充到 VO
}
5. 得到想要的组装对象
这里看起来业务场景还是比较简单,但是有两个问题:
1. 这里用户的操作是查询 list,组装 map,根据 key 获取 map,将对象放到 VO,如果对象有多个,那么用户的代码里面会有很多重复的,占据大篇幅代码量的该操作序列代码;
2. 如果附属对象有多个对象,那就会有多个 map 对象,这些对象内容很大,在全部循环结束前,所有的对象都不会被释放,占用着内存; 这个工具类的核心思想是采用反射,为了增加反射速度,引用 reflectasm 的类库,并且将 MethodAccess 对象通过 classType 缓存起来,加快反射执行速度:类的字段:
- private static final int MAX_CACHE_FOR_METHOD_ACCESS = 256; // 规定最大的缓存数量
- private static Map<Class, MethodAccess> methodAccessMap;// 缓存存放的map,在第一次使用时候才初始化
类的签名:
public void setField(Object obj1, String str1, Object obj2);// 将 obj1 的名为 str1 的字段值设置为 obj2
在 list 中拿一个对象,取出字段名为 <keyName> 的字段值,在 messMap 中查找 value,将 value 设置到 <valueName> 的字段中去
isStr 判断 valueName 的字段是否是字符串类型,如果是,对于 null 的处理会显示未 "", 如果不是则不做处理
/**
* 批量设置内容到 list 中
* @param list 需要附加内容的 list
* @param messMap 提供信息的 map,key=keyName
* @param keyName key(1.list 中有)
* @param valueName valueName(2.list 中有)
* @param isStr 设置的值是否是字符串
*/
public static void setField(List list, Map messMap, String keyName, String valueName, boolean isStr);
public void setFieldStr(List, Map, String, String); // 调用 setField(list, map, String, String, true)
public void setField(List, Map, String, String);// 调用 setField(list, map, String, String, false)
private void initmethodAccessMap();// 初始化缓存 map
private void delOneFromMap;// 从 map 中随机清理一个
private void addMethodAccessCache(Class, MethodAccess);// 添加缓存到 map
private MethodAccess getMethodAccess(Class);// 通过 class 获取缓存的 methodAccess
- /**
- * 批量设置内容到list中
- * @param list 需要附加内容的list
- * @param messMap 提供信息的map,key=keyName
- * @param keyName key(1.list中有)
- * @param valueName valueName(2.list中有)
- * @param isStr 设置的值是否是字符串
- */
- public static void setField(List list, Map messMap, String keyName, String valueName, boolean isStr) {
- if (ListUtil.isNull(list)) {
- logger.info("iii= list is null/empty. =iii");
- return;
- }
- if (MapUtils.isEmpty(messMap)) {
- logger.info("iii= messMap is null/empty. =iii");
- return;
- }
- if (keyName == null) {
- logger.info("iii= keyName is null. =iii");
- return;
- }
- initmethodAccessMap();
- Class clazz = list.get(0).getClass();
- MethodAccess ma = getMethodAccess(clazz);
- String setValueMethodName = "set" + StrFormatUtil.captureName(valueName);
- int setValueMethodIndex = ma.getIndex(setValueMethodName);
- String getKeyMethodName = "get" + StrFormatUtil.captureName(keyName);
- int getKeyMethodIndex = ma.getIndex(getKeyMethodName);
- for (Object object: list) {
- Object keyValue = ma.invoke(object, getKeyMethodIndex, keyName);
- Object value = messMap.get(keyValue);
- if (value == null && isStr) {
- value = "";
- }
- ma.invoke(object, setValueMethodIndex, value);
- }
- }
- /**
- * 设置内容到对象中
- * @param object 需要设置的内容
- * @param fieldName 字段名
- * @param fieldValue 设置的内容
- */
- public static void setField(Object object, String fieldName, Object fieldValue) {
- if (object == null) {
- logger.info("iii= object is null. =iii");
- return;
- }
- if (fieldName == null) {
- logger.info("iii= fieldName is null. =iii");
- return;
- }
- if (fieldValue == null) {
- logger.info("iii= fieldValue is null. =iii");
- return;
- }
- initmethodAccessMap();
- Class clazz = object.getClass();
- MethodAccess ma = getMethodAccess(clazz);
- String methodName = "set" + StrFormatUtil.captureName(fieldName);
- int methodIndex = ma.getIndex(methodName);
- ma.invoke(object, methodIndex, fieldValue);
- }
批量填充的情况,每次装填信息前,只要获取主对象 list,装填信息集合 map,设置两个字段名,即可完成。
第一次写博客,写得不好多多包涵。后面会坚持写,力求写出好而美的文章。
来源: http://www.bubuko.com/infodetail-2435242.html