内容简介:距离上上篇距离上一篇督促自己早日完成整个系列的文章,今天我将带领大家从字节码的层面来分析。
1. 前言
距离上上篇 【mica cglib 增强——【01】cglib bean copy 介绍】 已经过去一个月八一天。
距离上一篇 【Java Bean Copy 性能大比拼】 已过去一个月零一天。
督促自己早日完成整个系列的文章,今天我将带领大家从字节码的层面来分析。
注
:对于 java 字节码感兴趣的朋友也可以阅读 《Java虚拟机规范》,Oracle 官方也有 英文原版
的 pdf可供下载。
2. Bean 模型
我们列举2个模型 User
和 UserVo
,注意: birthday
字段类型不一样(敲黑板)。
2.1 User
@Data public class User { private Integer id; private String name; private Integer age; private LocalDateTime birthday; }
2.2 UserVo
@Data public class UserVo { private String name; private Integer age; private String birthday; }
3. Cglib Bean copy 字节码分析
3.1 配置 Cglib debug 模式
在第一篇 【mica cglib 增强——【01】cglib bean copy 介绍】 我们提到可以设置 cglib 源码生成目录。
// 设置 cglib 源码生成目录 String sourcePath = "/Users/lcm/git/mica/mica-example/web-example/src/test/java"; System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, sourcePath);
3.2 Bean copy 时生成的字节码
不使用类型转换时
Bean copy 的代码如下:
// 1. 初始化 user,赋值 User user = new User(); user.setId(250); user.setName("如梦技术"); user.setAge(30); user.setBirthday(LocalDateTime.now()); // 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, birthday=null) System.out.println(userVo);
生成的字节码:
package org.springframework.cglib.empty; import net.dreamlu.test.User; import net.dreamlu.test.UserVo; import org.springframework.cglib.beans.BeanCopier; import org.springframework.cglib.core.Converter; public class Object$$BeanCopierByCGLIB$$70f9539b extends BeanCopier { public Object$$BeanCopierByCGLIB$$70f9539b() { } public void copy(Object var1, Object var2, Converter var3) { UserVo var10000 = (UserVo)var2; User var10001 = (User)var1; var10000.setAge(((User)var1).getAge()); var10000.setName(var10001.getName()); } }
注意:
由于 birthday
字段类型不一样,没有生成 set
方法。
使用类型转换时
Bean copy 的代码如下:
// 1. 初始化 user,赋值 User user = new User(); user.setId(250); user.setName("如梦技术"); user.setAge(30); user.setBirthday(LocalDateTime.now()); // 2. 初始化 userVo UserVo userVo = new UserVo(); // 3. 构造 BeanCopier,不是用类型转换 BeanCopier copier = BeanCopier.create(User.class, UserVo.class, true); // 4. 拷贝对象,不是用类型转换,转换器可以使用 null copier.copy(user, userVo, new Converter() { @Override public Object convert(Object o, Class aClass, Object o1) { if (o == null) { return null; } // 直接使用 mica 中的类型转换工具 return ConvertUtil.convert(o, aClass); } }); // 5. 打印结果:UserVo(name=如梦技术, age=30, birthday=19-4-30 下午9:45) System.out.println(userVo);
生成的字节码:
package org.springframework.cglib.empty; import net.dreamlu.test.User; import net.dreamlu.test.UserVo; import org.springframework.cglib.beans.BeanCopier; import org.springframework.cglib.core.Converter; public class Object$$BeanCopierByCGLIB$$70f9539a extends BeanCopier { private static final Class CGLIB$load_class$java$2Elang$2EInteger; private static final Class CGLIB$load_class$java$2Elang$2EString; public Object$$BeanCopierByCGLIB$$70f9539a() { } public void copy(Object var1, Object var2, Converter var3) { UserVo var4 = (UserVo)var2; User var5 = (User)var1; var4.setAge((Integer)var3.convert(var5.getAge(), CGLIB$load_class$java$2Elang$2EInteger, "setAge")); var4.setBirthday((String)var3.convert(var5.getBirthday(), CGLIB$load_class$java$2Elang$2EString, "setBirthday")); var4.setName((String)var3.convert(var5.getName(), CGLIB$load_class$java$2Elang$2EString, "setName")); } static void CGLIB$STATICHOOK1() { CGLIB$load_class$java$2Elang$2EInteger = Class.forName("java.lang.Integer"); CGLIB$load_class$java$2Elang$2EString = Class.forName("java.lang.String"); } static { CGLIB$STATICHOOK1(); } }
注意:
使用类型转换后生成了 birthday
的 set
,仔细观察可以看到使用了类型转换之后生成的字节码都走了 类型转换
的逻辑。
4 Mica Bean copy的字节码
由于 Mica 的 Bean copy 是基于 Cglib 进行的增强查看字节码的方式和Cglib一样,设置的方式也和上面一样。
4.1 不使用类型转换
Bean copy 的代码如下:
// 1. 初始化 user,赋值 User user = new User(); user.setId(250); user.setName("如梦技术"); user.setAge(30); user.setBirthday(LocalDateTime.now()); // 2. 使用 mica 的 BeanUtil copy 方法 UserVo userVo = BeanUtil.copy(user, UserVo.class); // 3. 打印结果:UserVo(name=如梦技术, age=30, birthday=null) System.out.println(userVo);
生成的字节码:
package org.springframework.cglib.empty; import net.dreamlu.mica.core.beans.MicaBeanCopier; import net.dreamlu.test.User; import net.dreamlu.test.UserVo; import org.springframework.cglib.core.Converter; public class Object$$MicaBeanCopierByCGLIB$$aa75e50d extends MicaBeanCopier { public Object$$MicaBeanCopierByCGLIB$$aa75e50d() { } public void copy(Object var1, Object var2, Converter var3) { UserVo var4 = (UserVo)var2; User var5 = (User)var1; var4.setAge(var5.getAge()); var4.setName(var5.getName()); } }
注意:
不使用类型转换时生成的字节码同 Cglib
一致,只是使用更加简单一些。
4.2 使用类型转换时
Bean copy 的代码如下:
// 1. 初始化 user,赋值 User user = new User(); user.setId(250); user.setName("如梦技术"); user.setAge(30); user.setBirthday(LocalDateTime.now()); // 2. 使用 mica 的 BeanUtil copyWithConvert 方法 UserVo userVo = BeanUtil.copyWithConvert(user, UserVo.class); // 3. 打印结果:UserVo(name=如梦技术, age=30, birthday=19-4-30 下午10:04) System.out.println(userVo);
生成的字节码:
package org.springframework.cglib.empty; import net.dreamlu.mica.core.beans.MicaBeanCopier; import net.dreamlu.test.User; import net.dreamlu.test.UserVo; import org.springframework.cglib.core.Converter; public class Object$$MicaBeanCopierByCGLIB$$aa75e0e7 extends MicaBeanCopier { private static final Class CGLIB$load_class$java$2Elang$2EString; public Object$$MicaBeanCopierByCGLIB$$aa75e0e7() { } public void copy(Object var1, Object var2, Converter var3) { UserVo var4 = (UserVo)var2; User var5 = (User)var1; var4.setAge(var5.getAge()); var4.setBirthday((String)var3.convert(var5.getBirthday(), CGLIB$load_class$java$2Elang$2EString, "birthday")); var4.setName(var5.getName()); } static void CGLIB$STATICHOOK1() { CGLIB$load_class$java$2Elang$2EString = Class.forName("java.lang.String"); } static { CGLIB$STATICHOOK1(); } }
注意:
可以看到 Mica 中对生成的字节码进行了优化,对类型相同的拷贝不使用类型转换。
总结
在 Mica 中笔者对 Bean Copy 进行了大量的优化,包括类型转换优化,链式Bean支持,Map支持等,敢兴趣的朋友可以试用哦。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- Clojure 运行原理之字节码生成剖析 | Keep Writing Codes
- 主机字节序和网络字节序
- 操作 Java 字节码
- JVM基础 -- 字节码
- 字节跳动的面试感受
- dalvik字节码初识
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Linux/Unix设计思想
甘卡兹 / 漆犇 / 人民邮电出版社 / 2012-3-28 / 39.00元
《Linux\Unix设计思想/图灵程序设计丛书》内容简介:将Linux的开发方式与Unix的原理有效地结合起来,总结出Linux与Unix软件开发中的设计原则。《Linux\Unix设计思想/图灵程序设计丛书》前8章分别介绍了Linux与Unix中9条基本的哲学准则和10条次要准则。第9章和第10章将Unix系统的设计思想与其他系统的设计思想进行了对比。最后介绍了Unix哲学准则在其他领域中的应......一起来看看 《Linux/Unix设计思想》 这本书的介绍吧!