普通的对象拷贝
1、对象之间的拷贝的方法有:
apache的BeanUtils:反射
apache的PropertyUtils:反射
spring的BeanUtils:反射
他们都用的是反射,性能很差,不建议使用。
cglib的BeanCopier:动态代理
用的是动态代理,性能很高,是上面的几十倍甚至上百倍。
2、使用 cglib的BeanCopier,需要引入的依赖
<!-- cglib的BeanCopier需要的依赖 -->
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-commons</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-util</artifactId>
<version>3.3.1</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>2.2.2</version>
</dependency>
3、工具类,封装BeanCopier
public class BeanCopierUtils {
/**
* BeanCopier缓存
*/
public static Map<String, BeanCopier> beanCopierCacheMap = new HashMap<String, BeanCopier>();
/**
* 将source对象的属性拷贝到target对象中去
* @param source source对象
* @param target target对象
*/
public static void copyProperties(Object source, Object target){
//把source对象的类名和target对象的类名拼起来,做为map的key
String cacheKey = source.getClass().toString() +
target.getClass().toString();
BeanCopier beanCopier = null;
if (!beanCopierCacheMap.containsKey(cacheKey)) {
synchronized(BeanCopierUtils.class) {
if (!beanCopierCacheMap.containsKey(cacheKey)) {
beanCopier = BeanCopier.create(source.getClass(), target.getClass(), false);
beanCopierCacheMap.put(cacheKey, beanCopier);
}
}
} else {
beanCopier = beanCopierCacheMap.get(cacheKey);
}
beanCopier.copy(source, target, null);
}
}
用享元模式将一个类到另一个类的BeanCopier给缓存起来。
4、每个pojo类都需要的clone方法
/**
* 克隆方法
* @param clazz 目标Class对象
* @return 克隆后的对象
*/
public <T> T clone(Class<T> clazz) {
T target = null;
try {
target = clazz.newInstance();
} catch (Exception e) {
logger.error("error", e);
}
BeanCopierUtils.copyProperties(this, target);
return target;
}
在每一个pojo对象中都可以写这么一段方法。
注意:如果是创建一个目标对象,一个个字段set过去,就不叫原型模式了。
改进,集合的拷贝
1、定义一个类,这个做为pojo的父类
public class AbstractObject {
public <T> T clone(Class<T> clazz) throws Exception {
T target = clazz.newInstance();
BeanCopierUtils.copyProperties(this, target);
return target;
}
}
然后让每个pojo类继承这个类,这样就不用在每个pojo类都定义一个clone方法。
2、BeanCopierUtils工具类没变。
有上面这两步就可以实现对象之间的拷贝了。
3、集合之间的拷贝
public class ObjectUtils {
/**
* 转换集合
* @param sourceList 源集合
* @param targetClazz 目标集合元素类型
* @return 转换后的集合
*/
public static <T> List<T> convertList(
List<? extends AbstractObject> sourceList, Class<T> targetClazz) throws Exception {
List<T> targetList = new ArrayList<T>();
for(AbstractObject sourceObject : sourceList) {
targetList.add(sourceObject.clone(targetClazz));
}
return targetList;
}
}
有了这个就可以实现集合之间的拷贝。
注意:这种方式是浅拷贝,如果拷贝的类中还包含了其他对象,则所含对象不能拷贝。