天天看點

mica cglib 增強——[1]cglib bean copy 介紹開源推薦

專欄介紹

本套專欄主要是介紹微服務核心架構 Mica 中對 Cglib bean copy 的一系列增強,保證高性能的同時,提高易用性。整個專欄有 6 篇文章,感興趣的朋友請加關注。

專欄目錄

  1. cglib bean copy 介紹。
  2. mica bean copy 介紹和鍊式 bean copy 的支援。
  3. mica bean 支援 copy 原始類型和封裝類型。
  4. mica bean 支援 copy map 到 bean。
  5. 使用Spring的類型轉換增強 mica bean copy。
  6. mica bean、Map 互轉增強和總結。

Cglib BeanCopier 介紹

阿裡巴巴 p3c 插件中有這麼一項檢查 “避免用Apache Beanutils進行屬性的copy,Apache BeanUtils性能較差,可以使用其他方案比如Spring BeanUtils, Cglib BeanCopier”。今天我們的主角主要就是 Cglib 的 BeanCopier。

性能

下圖是 github 上的一個 Bean copy 性能的對比,可以看出 Bean copy 工具性能差距還是比較大。

mica cglib 增強——[1]cglib bean copy 介紹開源推薦

更多請見:

https://github.com/yangtu222/BeanUtils#performance

圖中可以看出,Cglib BeanCopier 的性能十分強勁,也難怪阿裡巴巴規範中也推薦,下面我們來看看它具體的使用方式。

使用

Cglib 以源碼的形式納入到 Spring core 中,所有大家使用 Spring、Spring boot 可以直接使用。其它則需要自己添加依賴,下面的使用例子都以 Spring 的為主。注意:使用了

Lombok

User 對象

@Data
public class User {
   private Integer id;
   private String name;
   private Integer age;
}           

UserVo 對象

@Data
public class UserVo {
    private String name;
    private Integer age;
}           

Bean 拷貝

import org.springframework.cglib.beans.BeanCopier;

public class UserCopyTest {

    public static void main(String[] args) {
        // 1. 初始化 user,指派
        User user = new User();
        user.setId(250);
        user.setName("如夢技術");
        user.setAge(30);

        // 2. 初始化 userVo
        UserVo userVo = new UserVo();
        // 3. 構造 BeanCopier,不是用類型轉換
        BeanCopier copier = BeanCopier.create(User.class, UserVo.class, false);
        // 4. 拷貝對象,不是用類型轉換,轉換器可以使用 null
        copier.copy(user, userVo, null);

        // 5. 列印結果:UserVo(name=如夢技術, age=30)
        System.out.println(userVo);
    }
}           

原理

大家都知道 Cglib BeanCopier,之是以性能這麼高主要是利用了 Asm 位元組碼技術。

在 UserCopyTest 的 main 方法中添加下面的代碼(建議直接放置到 1. 初始化 user,指派 之前),指定cglib 源碼生成目錄,建議生成到 idea 項目中,可以直接打開生成的 class 位元組碼。

// 設定 cglib 源碼生成目錄
String sourcePath = "/Users/lcm/git/mica/mica-example/web-example/src/test/java";
System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, sourcePath);           

再次執行 main 方法。我們可以看到控制台列印下了這麼一行日志。

CGLIB debugging enabled, writing to '/Users/lcm/git/mica/mica-example/web-example/src/test/java'           

下面我們來看看生成的代碼:

mica cglib 增強——[1]cglib bean copy 介紹開源推薦

看到此圖大家恍然大悟,Cglib BeanCopier 幫我們生成了 get set 轉換。

Cglib copy 問題

  1. 不支援鍊式 bean,mybatis-plus 生成的 Model 中預設添加了 @Accessors(chain = true) 注解預設為鍊式。
  2. 不支援 原始類型和封裝類型 copy

    int <-> Integer

  3. 類型轉換不夠智能,設定 useConverter 為 true 和重寫 Converter,

    類型相同

    也會走轉換的邏輯。

注意:這部分後面會詳細介紹,喜歡的朋友請關注、訂閱我們。

連結

mica:

https://github.com/lets-mica/mica

如夢技術官網:

https://www.dreamlu.net

開源推薦