BeanUtils
提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean
的属性进行处理。我们知道,一个JavaBean
通常包含了大量的属性,很多情况下,对JavaBean
的处理导致大量get
/set
代码堆积,增加了代码长度和阅读代码的难度。
如果你有两个具有很多相同属性的JavaBean
,需要对象之间的赋值,这时候就可以使用这个方法,避免代码中全是get
/set
之类的代码,可以让代码简洁明朗更优雅。
BeanUtils是深拷贝,还是浅拷贝?
是浅拷贝。
浅拷贝: 只是调用子对象的set方法,并没有将所有属性拷贝。(也就是说,引用的一个内存地址)
深拷贝: 将子对象的属性也拷贝过去。
有子对象就一定不能用BeanUtils么
并不绝对,这个要区分考虑:
1、子对象还要改动。
2、子对象不怎么改动。
虽然有子对象,但是子对象并不怎么改动,那么用BeanUtils也是没问题的。
源码中的核心代码:
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) {
ResolvableType sourceResolvableType = ResolvableType.forMethodReturnType(readMethod);
ResolvableType targetResolvableType = ResolvableType.forMethodParameter(writeMethod, 0);
boolean isAssignable = !sourceResolvableType.hasUnresolvableGenerics() && !targetResolvableType.hasUnresolvableGenerics() ? targetResolvableType.isAssignableFrom(sourceResolvableType) : ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType());
if (isAssignable) {
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 var18) {
throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var18);
}
}
}
}
}
}
}
source
是源对象,target
是需要赋值的对象
赋值成功的属性对应的属性名和属性类型必须相同,否则对应的属性值不会从一个对象赋值给另一个对象,但是此时不影响其他属性值的拷贝。
Springboot已经集成了该依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
实现
@Data
@NoArgsConstructor
@AllArgsConstructor
@Accessors(chain = true)
public class User {
private String id;
private String username;
private String password;
private String salt;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO {
private String username;
private String password;
private String salts;
}
测试
@Test
public void test(){
User user = new User("1", "chen yang", "123", "abc");
UserDTO userDTO = new UserDTO();
System.out.println(userDTO);
BeanUtils.copyProperties(user,userDTO);
System.out.println(userDTO);
}
userDTO中的salts字段与User中的salt字段名不一致,所以无法赋值成功
当需要复制多个对象时,我们可以使用循环来进行操作
// 初始化数据
ArrayList<User> userList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
User users = new User("1"+i, "chen yang "+i, "abc"+i, "abc"+i);
userList.add(users);
}
ArrayList<UserDTO> userDTOList = new ArrayList<>();
userList.forEach(u -> {
UserDTO userD = new UserDTO();
BeanUtils.copyProperties(u, userD);
userDTOList.add(userD);
});
userDTO中的字段需要经常改动,我们可以使用stream流来操作
List<UserDTO> collect = userList.stream().map(u -> new UserDTO(u.getUsername(), u.getPassword(), u.getSalt())).collect(Collectors.toList());
当我们需要忽略某些属性的赋值时
copyProperties(Object source, Object target, String... ignoreProperties)
//定义username不赋值
String[] ignoreProperties = {"username"};
BeanUtils.copyProperties(user,userDTO,ignoreProperties);
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/95917.html