BeanUtils.copyProperties的使用

导读:本篇文章讲解 BeanUtils.copyProperties的使用,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

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);
    }

BeanUtils.copyProperties的使用

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

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!