作者:京东零售张斌1.Orika是什么?Orika是一个简单快速的JavaBean复制框架,可以递归地将数据从一个JavaBean复制到另一个JavaBean,这在多层应用程序开发中非常有用。2.为什么要介绍Orika?在我们的工作中,经常需要将对象转换成不同的形式来适配不同的API,或者在不同的业务层传递对象,不同层的对象格式不同,所以需要编写mappings代码,将对象中的属性值进行转换从一种类型到另一种类型。Orika用于简化多层之间的对象映射,避免在手工编码和基于反射的映射中挣扎。Orika专注于尽可能自动化,同时根据需要提供配置和扩展以进行定制。3、项目中常用的javabean映射技术Java反射:性能问题,无法解决嵌套javabean映射复制手动映射:硬编码,代码量大序列化方式:通过json和xml进行序列化和反序列化,字段参数不一致同时需要硬编码赋值4.常用的bean映射工具BeanUtils:apache的BeanUtils和spring的BeanUtils中复制方法的原理是先使用java.beans.Introspector类的getBeanInfo()方法jdk通过get/set方法获取对象的属性信息和属性,然后使用反射(Method的invoke(Objectobj,Object...args))方法进行赋值。Apache支持同名不同类型的属性转换,spring支持忽略某些不映射的属性。它们都设置了一个缓存来保存解析出来的BeanInfo信息。BeanCopier:cglib的BeanCopier采用了不同的方式:不使用反射给属性赋值,而是直接使用ASM的MethodVisitor,直接写每个属性的get/set方法(见BeanCopier类的generateClass(ClassVisitorv)方法针对具体流程)生成class文件并执行。因为直接生成字节码执行,所以BeanCopier的性能相比使用反射的BeanUtils有很大的提升。Orika:底层使用javassist类库生成Bean映射的字节码,然后直接加载并执行生成的字节码文件,所以速度比使用反射赋值快很多。Orika支持递归映射,它将映射嵌套类直到完成“简单”类型。它还包含一个故障保护功能,可以正确处理您尝试映射的对象中的递归引用。5.如何使用奥丽卡?5.1maven依赖ma.glasnost.orikaorika-core1.5.25.2两个javabean字段名是同映射MapperFactorymapperFactory=newDefaultMapperFactory.Builder().build();//MapperFactory.classMap(Person.class,PersonInfo.class).byDefault().register();MapperFactorymapperFacade=mapperFactory.getMapperFacade();Personperson=newPerson();person.setFirstName("张");person.setLastName("三");PersonInfopersonInfo=mapperFacade.map(person,PersonInfo.class);输出结果:5.3两个javabean字段名不相同mappingMapperFactorymapperFactory=newDefaultMapperFactory.Builder().build();mapperFactory.classMap(Person.class,PersonDesc.class).field("firstName","givenName")。field("lastName","sirName").byDefault().register();MapperFacademapperFacadeDesc=mapperFactory.getMapperFacade();PersonpersonNew=newPerson();personNew.setFirstName("King");personNew.setLastName("5");PersonDescpersonDesc=mapperFacadeDesc.map(personNew,PersonDesc.class);输出结果:5.4数组和列表映射javabeanpublicstaticclassPersonNameList{privateListnameList;publicPersonNameList(ListnameList){this.nameList=nameList;}//getter/setter方法}mapperFactory.classMap(PersonNameList.class,Person.class).field("nameList[0]","firstName").field("nameList[1]","lastName").register();ListnameParts=Arrays.asList(newString[]{"李","四"});Personperson=mapperFactory.getMapperFacade().map(newPersonNameList(nameParts),Person.class);输出结果:5.5同类型javabean复制(原型模式)MapperFactorymapperFactory=newDefaultMapperFactory.Builder().build();mapperFactory.classMap(Person.class,Person.class).byDefault()。register();Personperson=newPerson();person.setFirstName("张");person.setLastName("三");PersonpersonNew=mapperFactory.getMapperFacade().map(person,Person.class);输出结果:5.6嵌套javabean映射mapperFactory.classMap(Flight.class,Flight.class).byDefault().register();CabincabinY=newCabin("Y","8",1200);CabincabinF=newCabin("C","6",1900);CabincabinC=newCabin("F","A",2400);Flightflight=newFlight("CA1831",Lists.newArrayList(cabinY,cabinF,cabinC));FlightflightCopy=mapperFactory.getMapperFacade().map(flight,Flight.class);System.out.println("原始对象:flight="+JSON.toJSONString(flight));System.out.println("新对象:flightCopy="+JSON.toJSONString(flightCopy));flightCopy.setFlightNo("MU5183");flightCopy.getCabins().remove(0);System.out.println("修改航号和删除舱位:flightCopy="+JSON.toJSONString(flightCopy));System.out.println("原图:flight="+JSON.toJSONString(flight));输出结果:5.7List类映射MapperFactorymapperFactory=newDefaultMapperFactory.Builder().build();mapperFactory.classMap(Cabin.class,CabinDesc.class).byDefault().register();CabincabinY=newCabin("Y","8",1200);CabincabinF=newCabin("C","6",1900);CabincabinC=newCabin("F","A",2400);列表cabinList=Lists.newArrayList(cabinY,cabinF,cabinC);ListcabinDescList=mapperFactory.getMapperFacade().mapAsList(cabinList,CabinDesc.class);System.out.println("cabinList="+JSON.toJSONString(cabinList));System.out.println("cabinDescList="+JSON.toJSONString(cabinDescList));输出结果5.8自定义数据类型转换器(StringtoDate)继承接口CustomConverter类,外壳覆公共转换现convert类StringToDateConverter扩展CustomConverter{privateStringdateFormat;publicStringToDateConverter(StringdateFormat){this.dateFormat=dateFormat;}publicDateconvert(Strings,Typetype,MappingContextmappingContext){try{returnDateUtils.parseDate(s,dateFormat);}catch(Exceptione){e.printStackTrace();}返回空;}}MapperFactorymapperFactory=newDefaultMapperFactory.Builder().build();mapperFactory.getConverterFactory().registerConverter(newStringToDateConverter("yyyy-MM-dd"));mapperFactory.classMap(ArrayMapper.PersonNameList.class,Person.class).field("nameList[0]","firstName").field("nameList[1]","lastName").field("nameList[2]","birthDate").register();ListnameParts=Arrays.asList(newString[]{"李","四","1989-10-11"});Personperson=mapperFactory.getMapperFacade().map(newArrayMapper.PersonNameList(nameParts),Person.class);System.out.println("nameParts="+JSON.toJSONString(nameParts));System.out.println("person="+JSON.toJSONStringWithDateFormat(person,"yyyy-MM-dd"));输出结果:6.各绘图工具的性能测试。每个方法先预热执行20次,然后执行10万次,得到每次执行的平均时间。7、参考官网:http://orika-mapper.github.io/orika-docs/intro.html其他:https://www.jianshu.com/p/5daf68dc5758http://tech.dianwoda.com/2017/11/04/高兴能特兴风福得豆英社工居折花/