这种情况, 要copy bean 是不是很难受 ,假如有N个字段名不一样,每个都要set,瞬间想砸键盘吗?
用个工具类,从此省下键盘钱,去撩妹不香吗?
上代码
1、来个注解
@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CopySourceName {
String value();
}
2、工具类
public class CopyBeanUtils {
/**
* ps:Test2 test2 = CopyBeanUtils.springCopyProperties(i1, Test2.class);
*
* @param source 原对象
* @param targetClass 目标对象class
* @param <T>
* @return copy完后的对象
*/
public static <T> T springCopyProperties(Object source, Class<T> targetClass) {
Assert.notNull(source, "targetClass must not be null");
T target = BeanUtils.instantiateClass(targetClass);
BeanUtils.copyProperties(source, target);
return target;
}
/**
* ps:Test2 test2 = CopyBeanUtils.copyProperties(i1, Test2.class);
*
* @param source 原对象
* @param targetClass 目标对象class
* @param <T>
* @return copy完后的对象
*/
public static <T> T copyProperties(Object source, Class<T> targetClass) {
Assert.notNull(source, "targetClass must not be null");
T target = BeanUtils.instantiateClass(targetClass);
copyProperties(source, target);
return target;
}
public static void copyProperties(Object source, Object target) throws BeansException {
copyProperties(source, target, null, (String[]) null);
}
public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansException {
copyProperties(source, target, editable, (String[]) null);
}
/**
* @param source 原对象
* @param target 目标对象
* @param ignoreProperties 排除某些不需要复制的属性
* @throws BeansException
*/
public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
copyProperties(source, target, null, ignoreProperties);
}
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
"] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
HashMap<String, String> copySourceNameMap = new HashMap<>();
for (Field field : actualEditable.getDeclaredFields()) {
CopySourceName annotation = field.getAnnotation(CopySourceName.class);
if (annotation != null) {
copySourceNameMap.put(field.getName(), annotation.value());
}
}
for (PropertyDescriptor targetPd : targetPds) {
Method writeMethod = targetPd.getWriteMethod();
String name = targetPd.getName();
String sourceName = copySourceNameMap.get(name);
if (sourceName != null) name = sourceName;
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(name))) {
PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), name);
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null &&
ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
} catch (Throwable ex) {
throw new FatalBeanException(
"Could not copy property '" + name + "' from source to target", ex);
}
}
}
}
}
}
}
3、测试类
@Data
@Accessors(chain = true)
public class Test1 {
private String str;
private List<String> userIds;
}
@Data
@Accessors(chain = true)
public class Test2 {
private String str;
@CopySourceName("userIds")
private List<String> userIdList;
}
public class test {
public static void main(String[] args) {
Test1 i1 = new Test1().setStr( "11").setUserIds(CollectionUtil.toList("i", "2222", "111"));
Test2 test2 = CopyBeanUtils.copyProperties(i1, Test2.class);
System.out.println(JSONUtil.toJsonStr(test2 ));
}
}
实现逻辑基本一致,增加了一点代码
工具类 对比 Spring 的 BeanUtils.copyProperties(source, target); 运行速度 单位ms
第一次 | 50次 | 5000次 | 50000次 | 1000000次 | 5000000次 |
---|---|---|---|---|---|
spring | 11 | 51 | 168 | 674 | 8429 |
工具类 | 6 | 71 | 260 | 1096 | 5312 |
第二次 | 50次 | 5000次 | 50000次 | 1000000次 | 5000000次 |
---|---|---|---|---|---|
spring | 10 | 65 | 200 | 638 | 7692 |
工具类 | 3 | 49 | 237 | 1184 | 4359 |
第三次 | 50次 | 5000次 | 50000次 | 1000000次 | 5000000次 |
---|---|---|---|---|---|
spring | 14 | 86 | 211 | 685 | 8100 |
工具类 | 4 | 80 | 259 | 1072 | 5266 |
第四次 | 50次 | 5000次 | 50000次 | 1000000次 | 5000000次 |
---|---|---|---|---|---|
spring | 27 | 71 | 157 | 715 | 8242 |
工具类 | 4 | 107 | 281 | 1082 | 3354 |
第五次 | 50次 | 5000次 | 50000次 | 1000000次 | 5000000次 |
---|---|---|---|---|---|
spring | 9 | 121 | 168 | 653 | 9455 |
工具类 | 3 | 85 | 232 | 1059 | 5726 |