开发中经常碰到这样的场景,从数据库查询出来全部的字段,但是有些字段是不想给
客户端看到,这时就需要将属性从DAO复制到传给客户端的DTO对象,如果采用get/set,
那显得很麻烦。可使用反射实现。
Spring框架的 org.springframework.beans.BeanUtils 类帮我们实现了这个功能。
例子
@Data class Source{ private String name; private int age; public Source(String name, int age) { this.name = name; this.age = age; } } @Data class Source1{ private String home; private boolean flag; public Source1(String home, boolean flag) { this.home = home; this.flag = flag; } } @Data class Target{ private String name; private int age; private String home; private boolean flag; }
测试
@Slf4j public class UserInfoDto { public static void main(String args[]){ Source source = new Source("libai",34); Source1 source1 = new Source1("nanning",true); Target target = new Target(); BeanUtils.copyProperties(source,target); BeanUtils.copyProperties(source1,target); log.debug("target = {}",target); } }
输出
15:19:33.992 [main] DEBUG com.cloud.microblog.gateway.dto.UserInfoDto - target = Target(name=libai, age=34, home=nanning, flag=true)
需要注意的是,每个Bean类的getter/setter方法必须实现。
实现源码
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 = getPropertyDescriptors(actualEditable); List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null; PropertyDescriptor[] var7 = targetPds; int var8 = targetPds.length; for(int var9 = 0; var9 < var8; ++var9) { PropertyDescriptor targetPd = var7[var9]; Method writeMethod = targetPd.getWriteMethod(); if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); 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 var15) { throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15); } } } } } }