栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

使用 Chameleon 进行高性能java类型转换,支持不同类型结构的转换

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用 Chameleon 进行高性能java类型转换,支持不同类型结构的转换

文章目录
  • 解决问题
  • 原理
  • 支持转换的情景
  • 使用
    • dependency
    • 方式1(惰性加载)
    • 方式2(通过注解预加载)
    • 方式3(自定义预加载)
  • 代码演示
    • AStruct.java
    • BStruct.java
    • CStruct.java
    • AInnerStruct.java
    • BInnerStruct.java
  • Good Luck~

Chameleon 是一款基于 javassist 动态字节码生成的高性能类型转换工具。
拥有比Spring的BeanUtils更高的性能。
通过动态加载类型转换类的方式,使Chameleon拥有很高的类型转换性能。

解决问题
  1. Spring 的 BeanUtils 类型转换效率相对不太理想;
  2. MapStruct 配置太过复杂;
原理
  1. 在首次转换两个类时,通过 javassist 生成两个类型之间相互转化的字节码类,加载到JVM中,并缓存下来;
  2. 根据两个对象的Class,找到缓存中转化两者的动态实现类,调用生成的方法,完成转换。

原理跟 MapStruct 相似,生成的转换类中使用Getter/Setter进行赋值,MapStruct 和 Chameleon 的效率相当;

不同的是,MapStruct 编译时生成转换类,Chameleon 运行时根据需要动态生成两者相互转换类;

Chameleon在惰性加载模式下,首次动态生成字节码并加载需要150ms左右;可以通过添加注解或者自定义适配选择器,来预加载类型转换类。

支持转换的情景

仅处理具有 getter/setter/is 函数的属性

  1. 类型相同,直接转换

    1.1 类型为List且泛型类相同,直接转换

    1.2 类型为List且泛型类不同,转换泛型类,再赋值

    1.3 类型为List且泛型类不同,目标值是String,原值不为空的情况下,将原值 toString 处理

  2. 类型不同,转换类型,再赋值

    2.1 如果目标值是String,原值不为空的情况下,将原值 toString 处理

使用 dependency

   cn.muzin
   chameleon
   1.0.1

方式1(惰性加载)

不预加载转换类,在需要的时候加载转换类

// 1. 根据 Class 进行转换
AStruct aStruct = new AStruct();
// ignore aStruct Code ...
BStruct bStruct = ChameleonUtil.transform(aStruct, BStruct.class);
 
// 第三个参数为true时,子类型不一致,但字段相同,也可以转换
BStruct bStruct = ChameleonUtil.transform(aStruct, BStruct.class, true);

// 2. 值拷贝
BStruct bStruct1 = new BStruct();
ChameleonUtil.transform(aStruct, bStruct1);

// 3. 按照 Class,进行集合的转换
List aStructList = new ArrayList();
List bStructList = ChameleonUtil.transform(aStructList, BStruct.class);
方式2(通过注解预加载)

在需要转换的类上面标记@ChameleonTransform注解,通过配置ChameleonTransformEnvironmentAdaptSelector
选择器,来预加载类型互转的转换类

注意:配置完成后,一定要调用ready方法!!!

// 添加 @ChameleonTransform 注解
@ChameleonTransform(dest = { BStruct.class, OtherStruct.class })
public class AStruct extends CStruct {
    // class code ...
}


// 配置 注解适配选择器, 扫描指定包下面的所有类(可添加多个包名)
ChameleonUtil.addEnvironmentAdaptSelector(
        new ChameleonTransformEnvironmentAdaptSelector()
        .addbasePackage("cn.muzin.chameleon")
);

// 告诉 Chameleon 已经准备好了,开始配置组建。
ChameleonUtil.ready();

// 开始转换目标对象...
AStruct aStruct = new AStruct();
// ignore aStruct Code ...
BStruct bStruct = ChameleonUtil.transform(aStruct, BStruct.class);
方式3(自定义预加载)

实现EnvironmentAdaptSelector接口,自定义加载类型转换规则。
根据自己的需要返回类型之间的1对1、1对多关系。

//  根据需要返回相应的结构对

StructPair       结构对
   +- StructToonePair         结构1对1
   +- StructToMultiPair       结构1对多
   

示例:

// 实现 EnvironmentAdaptSelector 接口
public class EnvironmentAdaptSelectorImpl implements EnvironmentAdaptSelector {

   public List selector() {
      // your code...
      return new ArrayList();
   }

}

// 通过 Chameleon 或者 ChameleonUtil 添加该适配选择器
ChameleonUtil.addEnvironmentAdaptSelector(
        new EnvironmentAdaptSelectorImpl()
        );

// 告诉 Chameleon 已经准备好了,开始配置组建。
ChameleonUtil.ready();

// 开始转换目标对象...
AStruct aStruct = new AStruct();
// ignore aStruct Code ...
BStruct bStruct = ChameleonUtil.transform(aStruct, BStruct.class);
代码演示

以下@Data为lombok的@Data注解,不想使用lombok,可以将@Data去掉,生成Getter/Setter.

@ChameleonTransform 在使用注解适配选择器时配置,可以不配置注解进行惰性加载,或者根据自定义适配选择器进行预加载。

AStruct.java
@ChameleonTransform(dest = { BStruct.class })
@Data
public class AStruct extends CStruct {
    private String name;
    private String age;
    private String weight;
    private String height;
    private String idcard;
    private String school;
    private String profile;
    private String photo;
    private AInnerStruct inner;
    private List innerList;
    private Integer ttt;
    private List signList;
    private List strList;
}
BStruct.java
@Data
public class BStruct extends CStruct {
    private String name;
    private String age;
    private String weight;
    private String height;
    private String idcard;
    private String school;
    private String profile;
    private String photo;
    private BInnerStruct inner;
    private List innerList;
    private String ttt;
    private List signList;
    private List strList;
}
CStruct.java
@Data
public class CStruct {
    private String namec;
}
AInnerStruct.java
@ChameleonTransform(dest = { BInnerStruct.class })
@Data
public class AInnerStruct {
    private String ppp;
}
BInnerStruct.java
@Data
public class BInnerStruct {
    private String ppp;
}

ChameleonUtil.transform(struct, class, Boolean) 函数 的第三个值用于控制类型不匹配也尝试进行转换。
如上:AStruct和BStruct中存在inner和innerList, 在 第三个值为true的情况下,内部类型不匹配也可以进行转换。
示例:

long st = 0;
long et = 0;

// 设置 class 文件存储位置,不设置时,默认在临时目录下,便于debug时,查看class的情况。
ChameleonUtil.setTmpDir("/Users/sirius/bucket/project/IdeaProjects/chameleon/target/dclass");

// 配置 注解适配选择器
ChameleonUtil.addEnvironmentAdaptSelector(
        new ChameleonTransformEnvironmentAdaptSelector()
                .addbasePackage("cn.muzin.chameleon")
);

st = System.currentTimeMillis();

// 开始根据注解 预加载 转换类
ChameleonUtil.ready();

et = System.currentTimeMillis();
System.out.println((et - st) + " ms ready");


AStruct aStruct = new AStruct();
AInnerStruct aInnerStruct = new AInnerStruct();
aInnerStruct.setPpp("asdf");
aStruct.setAge("23");
aStruct.setName("23");
aStruct.setHeight("23");
aStruct.setIdcard("23");
aStruct.setPhoto("23");
aStruct.setSchool("23");
aStruct.setWeight("23");
aStruct.setNamec("23");
aStruct.setInner(aInnerStruct);
aStruct.setTtt(123);

List longs = new ArrayList();
longs.add(123L);
longs.add(127L);
longs.add(125L);

aStruct.setSignList(longs);
aStruct.setStrList(longs);

ArrayList aInnerStructs = new ArrayList<>();
aInnerStructs.add(aInnerStruct);
aInnerStructs.add(aInnerStruct);
aStruct.setInnerList(aInnerStructs);

for(int o = 0; o < 10; o++) {
    st = System.currentTimeMillis();
    for (int i = 0; i < 10000000; i++) {
        BStruct bStruct = ChameleonUtil.transform(aStruct, BStruct.class, true);
    }
    et = System.currentTimeMillis();
    System.out.println((et - st) + " ms transform");
}

结果:

Good Luck~
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/353607.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号