在开发过程中经常需要深度复制对象,才用Spring的BeanCopier方案是个不错的选择。
直接看代码,先准备好实体类。
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class UserBean implements Serializable {
private static final long serialVersionUID = -6952319891279734655L;
private NameBean name;
private String phone;
private String sex;
private int age;
private Date birthdate;
private long money;
private Date createTime;
private String createUser;
private Date modifyTime;
private String modifyUser;
private String isValidate;
private String comments;
}
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class NameBean implements Serializable {
private static final long serialVersionUID = -2023200990550843496L;
private String firstName;
private String lastName;
private Date createTime;
private String createUser;
private Date modifyTime;
private String modifyUser;
private String isValidate;
private String comments;
}
import lombok.Data;
import java.beans.Transient;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Data
public class StudentBean {
private List listTitle = new ArrayList();
{
listTitle.add("Spring");
listTitle.add("Java");
}
private String name;
private String addr;
private String sex;
private int age;
private Date birthdate;
private Date createTime;
private String createUser;
private Date modifyTime;
private String modifyUser;
private String isValidate;
private String comments;
private NameBean nameBean;
}
import org.springframework.cglib.beans.BeanCopier;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
public class CGlibMapper {
//使用缓存提高效率
private static final ConcurrentHashMap mapCaches = new ConcurrentHashMap<>();
/***
* 通过类复制属性(同一个类其实就是克隆自己) 属性相同才能复制
* @param source 需要复制的对象
* @param target 目标类
* @param
* @param
* @return
*/
public static T mapper(O source, Class target) {
return baseMapper(source, target);
}
/**
* 通过类复制属性(同一个类其实就是克隆自己) 属性相同才能复制
* @param source 需要复制的对象
* @param target 目标类
* @param action 支持lambda操作
* @param
* @param
* @return
*/
public static T mapper(O source, Class target, Consumer action) {
T instance = mapper(source,target);
action.accept(instance);
return instance;
}
/**
* 通过类复制属性(同一个类其实就是克隆自己) 属性相同才能复制
* @param source 需要复制的对象
* @param target 目标类
* @param action 支持lambda操作
* @param
* @param
* @return
*/
public static T mapper(O source, Class target, UnaryOperator action) {
T instance = mapper(source,target);
return action.apply(instance);
}
/***
* 通过对象复制属性(同一个类其实就是克隆自己) 属性相同才能复制
* @param source
* @param target
* @param
* @param
* @return
*/
public static T mapperObject(O source, T target) {
String baseKey = generateKey(source.getClass(), target.getClass());
BeanCopier copier;
if (!mapCaches.containsKey(baseKey)) {
copier = BeanCopier.create(source.getClass(), target.getClass(), false);
mapCaches.put(baseKey, copier);
} else {
copier = mapCaches.get(baseKey);
}
copier.copy(source, target, null);
return target;
}
public static T mapperObject(O source, T target, Consumer action) {
mapperObject(source, target);
action.accept(target);
return target;
}
public static T mapperObject(O source, T target, UnaryOperator action) {
mapperObject(source, target);
return action.apply(target);
}
private static T baseMapper(O source, Class target) {
String baseKey = generateKey(source.getClass(), target);
BeanCopier copier;
if (!mapCaches.containsKey(baseKey)) {
copier = BeanCopier.create(source.getClass(), target, false);
mapCaches.put(baseKey, copier);
} else {
copier = mapCaches.get(baseKey);
}
T instance = null;
try {
//需要复制的对象必须要有无参构造器
instance = target.getDeclaredConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
}
copier.copy(source, instance, null);
return instance;
}
private static String generateKey(Class> class1, Class> class2) {
return class1.toString() + class2.toString();
}
}
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CGlibMapperTest {
public static UserBean createUser(){
UserBean user = new UserBean();
NameBean nameObj = new NameBean();
user.setName(nameObj);
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
user.setPhone("18576670069");
user.setSex("1");
user.setAge(10);
try {
user.setBirthdate(dateFormat.parse("1990-10-11"));
} catch (ParseException e) {
e.printStackTrace();
}
user.setMoney(99999l);
user.setCreateTime(new Date());
user.setCreateUser("张三");
user.setModifyTime(new Date());
user.setModifyUser("李四");
user.setIsValidate("1");
user.setComments("2020年疫情大爆发");
try {
nameObj.setCreateTime(dateFormat.parse("2020-03-06"));
} catch (ParseException e) {
e.printStackTrace();
}
nameObj.setCreateUser("王五");
nameObj.setModifyTime(new Date());
nameObj.setModifyUser("赵六");
nameObj.setIsValidate("1");
nameObj.setComments("2020年疫情大爆发");
return user;
}
public static void main(String[] args) {
UserBean user = CGlibMapperTest.createUser();
UserBean user2 = CGlibMapper.mapper(user,user.getClass());
System.out.println("1___"+user2);
UserBean user3 = CGlibMapper.mapper(user,user.getClass(),userBean -> {
userBean.getName().setFirstName("川_");
userBean.getName().setLastName("建国");
System.out.println("2___"+userBean);
return userBean;
});
CGlibMapper.mapper(user,StudentBean.class,studentBean -> {
studentBean.setName("张同学");
System.out.println("3___"+studentBean);
});
StudentBean studentBean1 = CGlibMapper.mapperObject(user,new StudentBean(),studentBean -> {
System.out.println(studentBean);
});
StudentBean studentBean2 = CGlibMapper.mapperObject(user,new StudentBean(),studentBean -> {
studentBean.setAddr("滨江一号");
studentBean.setName("美国骗子");
studentBean.setNameBean(CGlibMapper.mapper(user.getName(),NameBean.class));
System.out.println(studentBean);
return studentBean;
});
}
}
控制台输出看结果
"C:\Program Files\Java\jdk-10\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\idel2019\lib\idea_rt.jar=59569:D:\Program Files\JetBrains\idel2019\bin" -Dfile.encoding=UTF-8 -classpath D:\workplace\liwei\javaAction2\ModernJavaInAction-master\target\classes;C:\Users\Thinkpad\.m2\repository\org\openjdk\jmh\jmh-core\1.21\jmh-core-1.21.jar;C:\Users\Thinkpad\.m2\repository\net\sf\jopt-simple\jopt-simple\4.6\jopt-simple-4.6.jar;C:\Users\Thinkpad\.m2\repository\org\apache\commons\commons-math3\3.2\commons-math3-3.2.jar;C:\Users\Thinkpad\.m2\repository\org\openjdk\jmh\jmh-generator-annprocess\1.21\jmh-generator-annprocess-1.21.jar;C:\Users\Thinkpad\.m2\repository\io\reactivex\rxjava2\rxjava\2.2.2\rxjava-2.2.2.jar;C:\Users\Thinkpad\.m2\repository\org\reactivestreams\reactive-streams\1.0.2\reactive-streams-1.0.2.jar;C:\Users\Thinkpad\.m2\repository\com\typesafe\akka\akka-actor_2.12\2.5.16\akka-actor_2.12-2.5.16.jar;C:\Users\Thinkpad\.m2\repository\org\scala-lang\scala-library\2.12.6\scala-library-2.12.6.jar;C:\Users\Thinkpad\.m2\repository\com\typesafe\config\1.3.3\config-1.3.3.jar;C:\Users\Thinkpad\.m2\repository\org\scala-lang\modules\scala-java8-compat_2.12\0.8.0\scala-java8-compat_2.12-0.8.0.jar;C:\Users\Thinkpad\.m2\repository\com\typesafe\akka\akka-stream_2.12\2.5.16\akka-stream_2.12-2.5.16.jar;C:\Users\Thinkpad\.m2\repository\com\typesafe\akka\akka-protobuf_2.12\2.5.16\akka-protobuf_2.12-2.5.16.jar;C:\Users\Thinkpad\.m2\repository\com\typesafe\ssl-config-core_2.12\0.2.4\ssl-config-core_2.12-0.2.4.jar;C:\Users\Thinkpad\.m2\repository\org\scala-lang\modules\scala-parser-combinators_2.12\1.1.1\scala-parser-combinators_2.12-1.1.1.jar;C:\Users\Thinkpad\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Thinkpad\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\Thinkpad\.m2\repository\org\projectlombok\lombok\1.18.12\lombok-1.18.12.jar;C:\Users\Thinkpad\.m2\repository\com\esotericsoftware\kryo\5.0.0-RC6\kryo-5.0.0-RC6.jar;C:\Users\Thinkpad\.m2\repository\com\esotericsoftware\reflectasm\1.11.8\reflectasm-1.11.8.jar;C:\Users\Thinkpad\.m2\repository\org\objenesis\objenesis\3.0.1\objenesis-3.0.1.jar;C:\Users\Thinkpad\.m2\repository\com\esotericsoftware\minlog\1.3.1\minlog-1.3.1.jar;C:\Users\Thinkpad\.m2\repository\net\sf\json-lib\json-lib\2.4\json-lib-2.4-jdk15.jar;C:\Users\Thinkpad\.m2\repository\commons-beanutils\commons-beanutils\1.8.0\commons-beanutils-1.8.0.jar;C:\Users\Thinkpad\.m2\repository\commons-collections\commons-collections\3.2.1\commons-collections-3.2.1.jar;C:\Users\Thinkpad\.m2\repository\commons-lang\commons-lang\2.5\commons-lang-2.5.jar;C:\Users\Thinkpad\.m2\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;C:\Users\Thinkpad\.m2\repository\net\sf\ezmorph\ezmorph\1.0.6\ezmorph-1.0.6.jar;C:\Users\Thinkpad\.m2\repository\asm\asm\3.3.1\asm-3.3.1.jar;C:\Users\Thinkpad\.m2\repository\asm\asm-commons\3.3.1\asm-commons-3.3.1.jar;C:\Users\Thinkpad\.m2\repository\asm\asm-tree\3.3.1\asm-tree-3.3.1.jar;C:\Users\Thinkpad\.m2\repository\org\springframework\spring-context\4.0.7.RELEASE\spring-context-4.0.7.RELEASE.jar;C:\Users\Thinkpad\.m2\repository\org\springframework\spring-aop\4.0.7.RELEASE\spring-aop-4.0.7.RELEASE.jar;C:\Users\Thinkpad\.m2\repository\aopalliance\aopalliance\1.0\aopalliance-1.0.jar;C:\Users\Thinkpad\.m2\repository\org\springframework\spring-beans\4.0.7.RELEASE\spring-beans-4.0.7.RELEASE.jar;C:\Users\Thinkpad\.m2\repository\org\springframework\spring-expression\4.0.7.RELEASE\spring-expression-4.0.7.RELEASE.jar;C:\Users\Thinkpad\.m2\repository\org\springframework\spring-core\4.0.7.RELEASE\spring-core-4.0.7.RELEASE.jar com.gufu.liwei.j2se.object.cloneobj.CGlibMapperTest
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils$2 (file:/C:/Users/Thinkpad/.m2/repository/org/springframework/spring-core/4.0.7.RELEASE/spring-core-4.0.7.RELEASE.jar) to method java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils$2
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
1___UserBean(name=NameBean(firstName=null, lastName=null, createTime=Fri Mar 06 00:00:00 CST 2020, createUser=王五, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=赵六, isValidate=1, comments=2020年疫情大爆发), phone=18576670069, sex=1, age=10, birthdate=Thu Oct 11 00:00:00 CST 1990, money=99999, createTime=Tue Jun 02 16:03:19 CST 2020, createUser=张三, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=李四, isValidate=1, comments=2020年疫情大爆发)
2___UserBean(name=NameBean(firstName=川_, lastName=建国, createTime=Fri Mar 06 00:00:00 CST 2020, createUser=王五, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=赵六, isValidate=1, comments=2020年疫情大爆发), phone=18576670069, sex=1, age=10, birthdate=Thu Oct 11 00:00:00 CST 1990, money=99999, createTime=Tue Jun 02 16:03:19 CST 2020, createUser=张三, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=李四, isValidate=1, comments=2020年疫情大爆发)
3___StudentBean(listTitle=[Spring, Java], name=张同学, addr=null, sex=1, age=10, birthdate=Thu Oct 11 00:00:00 CST 1990, createTime=Tue Jun 02 16:03:19 CST 2020, createUser=张三, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=李四, isValidate=1, comments=2020年疫情大爆发, nameBean=null)
StudentBean(listTitle=[Spring, Java], name=null, addr=null, sex=1, age=10, birthdate=Thu Oct 11 00:00:00 CST 1990, createTime=Tue Jun 02 16:03:19 CST 2020, createUser=张三, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=李四, isValidate=1, comments=2020年疫情大爆发, nameBean=null)
StudentBean(listTitle=[Spring, Java], name=美国骗子, addr=滨江一号, sex=1, age=10, birthdate=Thu Oct 11 00:00:00 CST 1990, createTime=Tue Jun 02 16:03:19 CST 2020, createUser=张三, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=李四, isValidate=1, comments=2020年疫情大爆发, nameBean=NameBean(firstName=川_, lastName=建国, createTime=Fri Mar 06 00:00:00 CST 2020, createUser=王五, modifyTime=Tue Jun 02 16:03:19 CST 2020, modifyUser=赵六, isValidate=1, comments=2020年疫情大爆发))
Process finished with exit code 0