Redkale 技术详解 02 -- Creator构建对象
来源:互联网 发布:达梦数据库客户端工具 编辑:程序博客网 时间:2024/05/23 16:24
org.redkale.util.Creator是采用ASM技术来实现代替反射构造函数的对象构建类。在根据流反序列化成对象、数据表记录转换成对象时都需要构建对象。常见的处理办法是利用反射,如Gson框架中反序列化是通过反射进行对象创建。众所周知反射的性能是比较低的,所以Redkale需要自实现一个对象构建类。
Creator是一个接口, 只有一个public T create(Object... params)方法,可变参数既适合空参数的Constructor也适合含参数的Constructor。得利于Java 8的新语法特性可以在接口上加上静态方法,Creator对象可以通过Creator.create(Class clazz)方法创建。构建原理是通过Constructor的参数来动态创建的。
Constructor<T> constructor0 = null;for (Constructor c : clazz.getConstructors()) { //优先找public 的构造函数if (c.getParameterCount() == 0) { constructor0 = c; break; }}if (constructor0 == null) {//其次找非private带ConstructorProperties的构造函数 for (Constructor c : clazz.getDeclaredConstructors()) { if (Modifier.isPrivate(c.getModifiers())) continue; if (c.getAnnotation(ConstructorProperties.class) != null) { constructor0 = c; break; } }}if (constructor0 == null) {//再次找非private且带-parameters编译项的构造函数 java 8以上才支持 for (Constructor c : clazz.getDeclaredConstructors()) { if (Modifier.isPrivate(c.getModifiers())) continue; Parameter[] params = c.getParameters(); if (params.length == 0) continue; boolean flag = true; for (Parameter param : params) { try { clazz.getDeclaredField(param.getName()); } catch (Exception e) { flag = false; break; } } if (flag) { constructor0 = c; break; } }}if (constructor0 == null) {//最后找非private的空构造函数 for (Constructor c : clazz.getDeclaredConstructors()) { if (Modifier.isPrivate(c.getModifiers())) continue; if (c.getParameterCount() == 0) { constructor0 = c; break; } }}
从以上代码可以看出,根据优先级选择Constructor,为了减少学习成本,Creator直接重用了java.beans.ConstructorProperties注解,又因ConstructorProperties只能标记在Constructor上,因此定义一个Creator.ConstructorParameters注解,用于标记在Creator的create方法上。
public class Record { private final int id; private String name; @ConstructorProperties({"id", "name"}) Record(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}Record.class通过ASM自动构建与Record同package的Creator类如下:public final class Record_DynCreator implements Creator<Record> { @Override @Creator.ConstructorParameters({"id", "name"}) public Record create(Object... params) { if (params[0] == null) params[0] = 0; return new Record((Integer) params[0], (String) params[1]); }}
如上代码,若构造参数是primitive类,而Creator.create传入的参数可能是null,因此需要给null的primitive对象赋予默认值0。细心的人可能发现了Record的构造函数并不是public的,虽然Record_DynCreator与Record在同一package,但由于两者不是同一个ClassLoader,故不能直接new Record。Redkale曲线救国,通过URLClassLoader的私有方法在Record.class的ClassLoader加载Record_DynCreator。
if (loader instanceof URLClassLoader && !Modifier.isPublic(constructor.getModifiers())) { try { final URLClassLoader urlLoader = (URLClassLoader) loader; final URL url = new URL("memclass", "localhost", -1, "/" + newDynName.replace('/', '.') + "/", new URLStreamHandler() { @Override protected URLConnection openConnection(URL u) throws IOException { return new URLConnection(u) { @Override public void connect() throws IOException { } @Override public InputStream getInputStream() throws IOException { return new ByteArrayInputStream(bytes); } }; } }); Method addURLMethod = URLClassLoader.class.getDeclaredMethod("addURL", URL.class); addURLMethod.setAccessible(true); addURLMethod.invoke(urlLoader, url); resultClazz = urlLoader.loadClass(newDynName.replace('/', '.')); } catch (Throwable t) { //异常无需理会, 使用下一种loader方式 t.printStackTrace(); }}
如上代码,构建一个虚拟协议的URL来实现加载,若Record.class的ClassLoader不是URLClassLoader导致resultClazz为null则会抛出异常。
Creator是一个典型通过ASM构建一个简单功能地动态类,同类型还有 org.redkale.util.Attribute、org.redkale.util.Reproduce。
转载请注明出处:http://redkale.org/article_creator.html
- Redkale 技术详解 02 -- Creator构建对象
- Redkale 技术详解 01 -- 双亲委托模型
- Redkale 技术详解 03 -- Convert高性能序列化
- Qt Creator:对象模型
- Redkale RESTful 插件介绍
- cocos creator (四)构建android项目
- Xcode更新QT Creator无法构建
- Cocos Creator—最佳构建部署实践
- Unity3D技术之构建播放器管道详解
- Qt Creator 工程文件详解
- Ajax技术之XMLHttpRequest对象详解
- JavaScript中的ERROR对象技术详解
- qt creator创建cmake构建的程序,无法启动调试
- qt5.5版本的creator构建套件自动检测为警告
- Qt creator创建cmake构建的程序,无法启动调试
- cocos creator构建的时候设置初始场景
- Qt Creator中的.pro文件的详解
- 避免重复的对象构建 ——Reference Counting(引用计数)技术
- PHP实现各种经典算法
- 【LeetCode】007 Majority Element 少数服从多数
- 编译型语言和解释型语言
- 使用caffe的python接口实现内部参数可视化
- Check Box的详细用法
- Redkale 技术详解 02 -- Creator构建对象
- scala case匹配值
- 类(Classes)的定义与实现
- 【读书笔记】JavaScript图片库
- java 中 FTP通信 问题总结
- objectiveC修饰符 static extern const
- StringTokenizer类的使用
- 创建帧动画
- Search Paths 之 Framework Search Paths、Library Search Paths、Header Search Paths