JavaBean作为一种简单的Java类,可用作数据的载体。
针对这种简单的Java类,我们要想对其本身进行操作就可以使用内省操作。具体涉及的类有3个:Introspector,BeanInfo,PropertyDescriptor.
...
//通过Introspector获得Object类对应的JavaBean的BeanInfo,再通过BeanInfo获得所有属性的属性描述器。
BeanInfo beanInfo = Introspector.getBeanInfo(Object.class());
PropertyDescriptor[] pds = beanInfo.getPropertyDescriptors(); //属性描述器
for (PropertyDescriptor pd : pds){
if (pd.getName().equals(propertyName)){ //获取属性名
Method writeMethod = pd.getWriteMethod();
}
}
...
如上所示,在获取某个属性的方法后就可以对该JavaBean实例的该属性进行读写操作。而在web端,会涉及的DO,DTO类就可以看作一种JavaBean。因此我们就可以通过属性描述器PropertyDescriptor来对DO,DTO进行转换。下面是我依据该原理写的一个转换方法:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* implement the transformation of the DO, DTO and so on.
*
* @author shifang
* @date 18/9/4
*/
public class DomainTransformUtil {
private static Logger logger = LoggerFactory.getLogger(DomainTransformUtil.class);
private static SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd");
/**
* Caution: the param name of DO and DTO must be same!
* @param doList the List of DO(must not null)
* @param dtoList the List of DTO to store the result
* @param itemDO the type of DO eg. DO.class
* @param itemDTO the type of DTO eg. DTO.class
* @return if successful, return true, else return false
*/
public static <DO, DTO> boolean do2Dto(List<DO> doList, List<DTO> dtoList, Class<DO> itemDO, Class<DTO> itemDTO){
return do2Dto(doList, dtoList, itemDO, itemDTO, fmt);
}
/**
* Caution: the param name of DO and DTO must be same!
* @param doList the List of DO(must not null)
* @param dtoList the List of DTO to store the result
* @param itemDO the type of DO eg. DO.class
* @param itemDTO the type of DTO eg. DTO.class
* @param fmt fmt is used to translate time from Date to String
* @return if successful, return true, else return false
*/
public static <DO, DTO> boolean do2Dto(List<DO> doList, List<DTO> dtoList, Class<DO> itemDO, Class<DTO> itemDTO, SimpleDateFormat fmt){
BeanInfo doBeanInfo = null;
try {
doBeanInfo = Introspector.getBeanInfo(itemDO);
} catch (IntrospectionException e) {
logger.error("getting BeanInfo of itemDO is error",e);
return false;
}
PropertyDescriptor[] doDescriptors = doBeanInfo.getPropertyDescriptors();
HashMap<String, PropertyDescriptor> doDescriptorMap = new HashMap<>();
for(PropertyDescriptor doDescriptor : doDescriptors){
doDescriptorMap.put(doDescriptor.getName(), doDescriptor);
}
if (doList.size() != 0) {
for(DO instanceDO : doList){
DTO instanceDTO;
try {
instanceDTO = itemDTO.newInstance();
} catch (InstantiationException e) {
logger.error("DTO instance failure",e);
return false;
} catch (IllegalAccessException e) {
logger.error("DTO instance failure",e);
return false;
}
BeanInfo dtoBeanInfo = null;
try {
dtoBeanInfo = Introspector.getBeanInfo(itemDTO);
} catch (IntrospectionException e) {
logger.error("get BeanInfo of dtoList error",e);
return false;
}
PropertyDescriptor[] dtoDescriptors = dtoBeanInfo.getPropertyDescriptors();
for(PropertyDescriptor dtoDescriptor : dtoDescriptors){
String propertyName = dtoDescriptor.getName();
if ("class".equals(propertyName)) continue;
Method methodOfDTOWrite = dtoDescriptor.getWriteMethod();
PropertyDescriptor descriptor = doDescriptorMap.get(propertyName);
Method methodOfDORead = descriptor.getReadMethod();
try {
Object value = methodOfDORead.invoke(instanceDO);
if (value instanceof BigDecimal) {
methodOfDTOWrite.invoke(instanceDTO, ((BigDecimal) value).toPlainString());
} else if (value instanceof Date) {
methodOfDTOWrite.invoke(instanceDTO, fmt.format((Date)value));
} else {
methodOfDTOWrite.invoke(instanceDTO, value.toString());
}
} catch (IllegalAccessException e) {
logger.error("can't access the instance of DTO", e);
return false;
} catch (InvocationTargetException e) {
logger.error("invocation failure", e);
return false;
}
}
dtoList.add(instanceDTO);
}
}
return true;
}
}