最近有个需求就是实体之间自动转换,网上肯定有很多现成的实现,不过还是自己写了一个,就当对java高级特性的一个熟悉的过程。这中间包含了泛型,反射,lamada表达式。对于想了解java高级特性的人来说,这也算一个不错的实战例子。
1,变化的需求。
当0.1版本的时候,能做的就是将完全匹配的字段名称mapper过去,但是没有多久发现这个远不能满足需求。
0.2版本,将原来代码加了toLowerCase(),不在区分大小写。之后就发现有些字段名称不一样了。
0.3版本,可以添加一些全局设置,可以在全局找到相关字段,把不匹配的转换过去。
0.4....可以想象还有很多比如全局设置和自动匹配顺序问题,还有每次修改都要改动mapper源代码,风险性很高,所以进行了一次重构,也就是产生了现在的1.0版本。
2,1.0版本
将原来只有处理逻辑mapper类拆分为两部分,映射的AutoMapper类,以及映射的逻辑MapperPolicy接口。AutoMapper类能够根据配置的MapperPolicy的配置进行mapper,提高灵活性,也保证业务逻辑分隔。并且加入了注解配置的方式,进一步提高灵活性。不过这个版本也只是一个雏形,还不是一个能够广泛使用的版本,以后肯定还要升级到1.1,1.2......
闲话少说,show me code。
1 public classAutoMapper {2 //策略数组
3 private List> policyList = new ArrayList<>();4
5 private boolean hasInit = false;6
7 //默认策略
8 private List>getDefaultMapperPolicy() {9 List> defaultPolicyList = new ArrayList<>();10 defaultPolicyList.add(() ->UseAnnotationMapperPolicy.getInstance());11 defaultPolicyList.add(() ->IgnoreCaseMapperPolicy.getInstance());12 returndefaultPolicyList;13 }14
15 //初始化
16 private voidinit() {17 if(hasInit) {18 return;19 }20 if (policyList == null ||policyList.isEmpty()) {21 policyList.addAll(getDefaultMapperPolicy());22 hasInit = true;23 }24 }25
26 //重置策略
27 publicAutoMapper clearPolicy() {28 hasInit = false;29 policyList.clear();30 return this;31 }32
33 //添加策略
34 public AutoMapper addPolicy(SuppliermapperPolicySupplier) {35 policyList.add(mapperPolicySupplier);36 return this;37 }38
39 //添加策略
40 publicAutoMapper addPolicy(MapperPolicy mapperPolicy) {41 return addPolicy(() ->mapperPolicy);42 }43
44 //mapper核心类
45 public T2 mapModel(T1 source, Classdesc) {46 init();47 try{48 T2 descObj =desc.newInstance();49 Arrays.stream(desc.getDeclaredFields()).forEach(field ->{50 Object descFieldObject = null;51 for (SupplierpolicySupplie : policyList) {52 MapperPolicy policy =policySupplie.get();53 Field sourceField =policy.getField(field, source);54 if (sourceField == null) {55 continue;56 }57