利用反照写自动装配类或转换器
利用反射写自动装配类或转换器
工作的时候,时常会遇到需要对一些类重新装配的问题,例如,由于Java传递对象本质上是传引用,直接利用对象类型的参数,可能会修改该参数;但是实际工作中,我们往往不想修参数,但是又希望利用该参数,那怎么办呢?
只好重新拷贝一个对象。
如果该类有几十个字段(实际往往是这样),我们装配对象就太费体力了,而且冗长的装配代码可能也不是我们想要的。那怎么办呢??
(1)对于通用情况的处理
由于类中的字段都是私有的,而访问控制一般借助于相应的get和set方法。那好吧,我们就可以利用反射,遍历所有set方法,然后调用源对象的get方法。ok,通用情况搞定。
(2)如果有例外的字段呢,有些字段并没有get或set方法,有has...或isOpen,之类的方法,直接调用源对象的get方法显然不行。对于这些例外字段,有些需要,有些实际上拷贝的时候可以不要。因此,我们可以实际2个list存放这些字段:
specialFieldNameList 和 needProcessFieldsList ,前者存放所有特殊的字段,后面那个列表存放以上特殊字段中需要进行处理的字段。
ok,明确了需求,可以动工了,代码如下:
工作的时候,时常会遇到需要对一些类重新装配的问题,例如,由于Java传递对象本质上是传引用,直接利用对象类型的参数,可能会修改该参数;但是实际工作中,我们往往不想修参数,但是又希望利用该参数,那怎么办呢?
只好重新拷贝一个对象。
如果该类有几十个字段(实际往往是这样),我们装配对象就太费体力了,而且冗长的装配代码可能也不是我们想要的。那怎么办呢??
(1)对于通用情况的处理
由于类中的字段都是私有的,而访问控制一般借助于相应的get和set方法。那好吧,我们就可以利用反射,遍历所有set方法,然后调用源对象的get方法。ok,通用情况搞定。
(2)如果有例外的字段呢,有些字段并没有get或set方法,有has...或isOpen,之类的方法,直接调用源对象的get方法显然不行。对于这些例外字段,有些需要,有些实际上拷贝的时候可以不要。因此,我们可以实际2个list存放这些字段:
specialFieldNameList 和 needProcessFieldsList ,前者存放所有特殊的字段,后面那个列表存放以上特殊字段中需要进行处理的字段。
ok,明确了需求,可以动工了,代码如下:
public class BaseConverter { private final Logger logger = LoggerFactory.getLogger(this.getClass()); /** * 特殊字段列表,只针对有set方法的属性字段 */ private List<String> specialFieldNameList = new ArrayList<String>(); /** * 上述特殊字段列表(specialFieldNameList)中需要进行处理的字段列表 */ private List<String> needProcessFieldsList = new ArrayList<String>(); /** * 是否是例外方法 * @param methodName * @return */ public BaseConverter(){} public BaseConverter(List<String> specialFieldNameList, List<String> needProcessFieldsList) { super(); this.specialFieldNameList = specialFieldNameList; this.needProcessFieldsList = needProcessFieldsList; } public boolean isSpecialMethod(String methodName) { List<String> specialFieldNameList = this.getSpecialFieldNameList(); String targetField = methodName.substring(3, 4).toLowerCase() + methodName.substring(4); if (specialFieldNameList.contains(targetField)) return true; else return false; } /** * 处理该特殊方法的返回值 * @param methodName * @return */ public boolean needProcess(String methodName) { List<String> needProcessFieldsList = this.getNeedProcessFieldsList(); String targetField = methodName.substring(3, 4).toLowerCase() + methodName.substring(4); if (needProcessFieldsList.contains(targetField)) return true; else return false; } public Object processSpecialMethod(Method targetMethod, Object srcObject, Object targetObject){ String targetMethodName = targetMethod.getName(); //此处省略 。。。。 targetMethod.invoke(targetObject, value); } catch (Exception e) { // e.printStackTrace(); logger.error("[Error:processSpecialMethod....encount an error]",e.getMessage()); } } return targetObject; } /** * * @param targetMethod * @param srcObject * @param targetObject * @return * @throws Exception */ public Object processTargetMethod(Method targetMethod, Object srcObject, Object targetObject) throws Exception { String targetMethodName = targetMethod.getName(); // logger.info("[Info:processTargetMethod]:"+ targetMethodName); if (targetMethodName.substring(0, 3).contains("set")) { // 先处理一般属性的字段 if (!isSpecialMethod(targetMethodName)) { // 先处理一般属性的字段 Method srcMethod = srcObject.getClass().getMethod( ("g" + targetMethodName.substring(1))); Object value = srcMethod.invoke(srcObject); targetMethod.invoke(targetObject, value); } else if (needProcess(targetMethodName)) { targetObject = this.processSpecialMethod(targetMethod, srcObject, targetObject); } } return targetObject; } /** * DO对象转换 * @param srcObject * @param targetObject * @return * @throws Exception */ public Object convertToObject(Object srcObject, Object targetObject) throws Exception { if(srcObject == null) return null; Class<?> targetClass = targetObject.getClass(); Method[] methods = targetClass.getDeclaredMethods(); Method targetMethod; for (int j = 0; j < methods.length; j++) { targetMethod = methods[j]; targetObject = this.processTargetMethod(targetMethod, srcObject, targetObject); targetObject = this.processTargetMethod(targetMethod, srcObject, targetObject); } Method[] superMethods = null; Class<?> superClass; while ((superClass = targetClass.getSuperclass()) != null) { superMethods = targetClass.getSuperclass().getDeclaredMethods(); for (int j = 0; j < superMethods.length; j++) { targetMethod = superMethods[j]; targetObject = this.processTargetMethod(targetMethod, srcObject, targetObject); } targetClass = superClass; } return targetObject; } public void setSpecialFieldNameList(List<String> specialFieldNameList) { this.specialFieldNameList = specialFieldNameList; } public List<String> getSpecialFieldNameList() { return specialFieldNameList; } public List<String> getNeedProcessFieldsList() { return needProcessFieldsList; } public void setNeedProcessFieldsList(List<String> needProcessFieldsList) { this.needProcessFieldsList = needProcessFieldsList; } }