copyProperties 对象属性的copy 支持Optional

Beanutils.copyProperties

最简单的使用spring的Beanutils

    UserPO source = userRepository.getOne(1L);//name:source id:2
    UserPO target= new UserPO();
    BeanUtils.copyProperties(source, target);
    //这实际上是使用了调用了source的get方法 然后再调用target的set方法. 可以看作是一个浅拷贝
    public class UserPO {

        private Long id;

        private String name;

        public void setId(Long id) {
            this.id = id;
        }

        public Long getId() {
            return id;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Optional<String> getName() {
            return Optional.ofNullable(name);
        }
    }
问题

但是你会发现这个Beanutils.copyProperties并不能将source的 name属性赋给target. 原因如下

BeanUtils使用的Introspector(内省). Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors() 将会返回一个PropertyDescriptor数组.
PropertyDescriptor对象就是你的get方法(和是否有这个属性无关)对应的一个属性值的详情(对应的get set方法) 举例

public class User {
    private String name;
    public String getId(){}
}
//getPropertyDescriptors()返回的数组里面不会有name但是会有id

因此一开始的UserPO得到的PropertyDescriptor 对象只有一个类型为 Long 的id 和一个类型为Optional 的name.而 setName方法是String类型的因此 这个name 的PropertyDescriptor 对象不存在set方法.
所以只能自己用内省简单的写一个方法:

public static<T> T copyBean(Object obj , T target){
    if(obj == null || target == null){
        return null;
    }
    try {
        //少用getBeanInfo的第二个参数 性能极差
        PropertyDescriptor[] objDescriptors = Introspector.getBeanInfo(obj.getClass()).getPropertyDescriptors();
        MethodDescriptor[] targetMethodDescriptor = Introspector.getBeanInfo(target.getClass()).getMethodDescriptors();
        for (PropertyDescriptor property : objDescriptors) {
            String key = property.getName();
            // 过滤class属性
            if (!key.equals("class") && property.getReadMethod() != null) {
                // 将属性第一位大写
                String setName = "set"+StringUtil.toUpStart(key);
                Object value = property.getReadMethod().invoke(obj);
                Optional<MethodDescriptor> targetSetMethod = Arrays.stream(targetMethodDescriptor).filter(a -> a.getName().equals(setName)).findFirst();
                if(targetSetMethod.isPresent()){
                    if(value instanceof Optional){
                        value = ((Optional) value).orElse(null);
                    }
                    targetSetMethod.get().getMethod().invoke(target,value);
                }
            }
        }
    } catch (Exception e) {
        log.warn("copyBean error",e);
    }
    return target;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值