BeanCopier浅拷贝嵌套对象分析

最近项目中使用了BeanCopier,但是使用过程中,存在有些数据无法拷贝成功的情况,故特地进行了整理。

1. 素材准备

对象A,A1,A2表示源对象,B,B1,B2表示目标对象。
A1,B1表示嵌套对象的场景
A2,B2表示嵌套集合的场景
示例如下:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class A {
    private String name;
}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class A1 {
    private long id;
    private A a;

}

@Data
@NoArgsConstructor
@AllArgsConstructor
public class A2 {
    private long id;
    private List<A> list;

}


@Data
public class B {
    private String name;
    private int age;
}

@Data
public class B1 {
    private long id;
    private B a;

}

@Data
public class B2 {
    private long id;
    private List<B> list;

}
public class Solution {

    public static void main(String[] args) {
    	// 此处设置生成的代理对象路径
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "D:\\logs");

        A a = new A("测试A");
        List<A> list = new ArrayList<>();
        list.add(a);
        A1 a1 = new A1(1,a);
        A2 a2 = new A2(2,list);

        // 包含对象
        BeanCopier copier = BeanCopier.create(A1.class, B1.class,false);
        B1 b1 = new B1();
        copier.copy(a1, b1,null);
        System.out.println(JSON.toJSON(b1));
        // 包含List
        BeanCopier copier1 = BeanCopier.create(A2.class, B2.class,false);
        B2 b2 = new B2();
        copier1.copy(a2, b2,null);
//      b2.getList().get(0).setAge(22);
        System.out.println(JSON.toJSON(b2));
    }


}

2.执行分析

执行完上文的main方法,进入上文设置的目录,可以发现生成了三个文件class,其中一个是BeanCopierKey文件,这里不关心。主要看下另外的文件。
一个对应嵌套对象的场景,如下:

public class Object$$BeanCopierByCGLIB$$e225ae67 extends BeanCopier {
    public Object$$BeanCopierByCGLIB$$e225ae67() {
    }

    public void copy(Object var1, Object var2, Converter var3) {
    	// 这里只进行基本属性设置,嵌套对象未设置
        ((B1)var2).setId(((A1)var1).getId());
    }
}

一个对应嵌套List的场景,如下:

public class Object$$BeanCopierByCGLIB$$d653fb7d extends BeanCopier {
    public Object$$BeanCopierByCGLIB$$d653fb7d() {
    }

    public void copy(Object var1, Object var2, Converter var3) {
        B2 var10000 = (B2)var2;
        A2 var10001 = (A2)var1;
        var10000.setId(((A2)var1).getId());
        // 这里List使用了相同的引用
        var10000.setList(var10001.getList());
    }
}

从这两个类文件可以很直观看出,BeanCopier是通过生成代理对象,进行了set/get操作。
放开上文中的 如下注释,再次Debug运行

//      b2.getList().get(0).setAge(22);

在这里插入图片描述

运行到b2.getList().get(0).setAge(22)处, 会抛出类型转换异常:

Exception in thread "main" java.lang.ClassCastException

3. 结论

  1. BeanCopier拷贝基本属性是以属性名进行设置的
  2. BeanCopier拷贝嵌套对象不会进行设置,即使属性名称一致
  3. BeanCopier拷贝集合对象使用了相同引用,故而拷贝之后对集合数据进行set操作,会报类型转换错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值