Redkale 技术详解 02 -- Creator构建对象
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。
相关推荐
三国小小将-客户端-creator.zip源码cocos creator项目源码下载三国小小将-客户端-creator.zip源码cocos creator项目源码下载 1.上线产品适合个人学习技术做项目参考 2.开发脚本为javsScropt或者typeScript 3.上线...
方块鸟-精品-creator.zip源码cocos creator项目源码下载方块鸟-精品-creator.zip源码cocos creator项目源码下载 1.适合个人学习技术做项目参考 2.开发脚本为javsScropt或者typeScript 3.适合小公司开发游戏项目参考
Cocos Creator 3D开发入门----CocosCreator3D篮球.zip import { _decorator, Component, Node, RigidBodyComponent, PhysicMaterial, ColliderComponent } from "cc"; const { ccclass, property } = _...
Altium Designer logo创建脚本,解压后使用AD运行该脚本即可将灰度BMP图片转换为PCB log0.(AD17亲测可用)!
原生Win7系统不包含USB3.0的驱动,所以无法使用USB3.0的U盘在USB3.0的设备上引导,且安装完系统后还需要重新安装USB3.0驱动。...Win7-USB3.0-creator-V3-Win7admin.zip - 用于64位 Windows7admin 系统安装
Win7-USB3.0-Creator-V3-Win7Admin.7z
cocos creator实例--使用creator简单实现连连看游戏 | 附代码。点击相同的两个动物图案,会消失一个选中框,然后就会消失掉
D0_A1 qt-4.8.6 qtcreator-3.2.2 part2 配合mingw-w64使用,包含32位和64位版本
台湾 今年嵌入式 课程课件,绝对技术紧跟国际 台湾嵌入式ptf文档和pptRM-033-04-101_Creator-PXA270
Simple-Bot-Creator-源码.rar
High-Logic FontCreator官方版是一款高效实用的专业化字体设计辅助工具,High-Logic FontCreator最新版功能强劲,能够帮助用户进行专业级的字体编辑操作,High-Logic FontCreator软件界面美观,便捷好用,提供了相当...
在Win7安装U盘中加入USB3.0驱动的支持, intel usb 3.0驱动,win 7 安装ISO是不支持usb 3.0
欢乐球球-creator3d.zip源码cocos creator项目源码下载欢乐球球-creator3d.zip源码cocos creator项目源码下载 1.上线产品适合个人学习技术做项目参考 2.开发脚本为javsScropt或者typeScript 3.上线产品适合小公司...
LINUXLIVE-USB-CREATOR-RAR
QT-Creator:编译版本是qt-creator-4.2.0 测试编译qt-creator-4.2.0 其他设备、系统、自行测试 ----------------------------------------------------------------------------- qt-creator-4.2.0,亲测可用 qt-...
QT-Creator:编译版本是qt-creator-4.0.3 测试编译qt-creator-4.0.3 其他设备、系统、自行测试 ----------------------------------------------------------------------------- qt-creator-4.0.3,亲测可用 qt-...
资源来自pypi官网。 资源全名:music-score-creator-0.9.1.tar.gz
资源来自pypi官网。 资源全名:lambda-project-creator-0.0.4.tar.gz
编译版本是:QT-creator-4.8.2 测试编译QT-creator-4.8.2,亲测可用 其他设备、系统、自行测试 ----------------------------------------------------------------------- QT-creator-4.8.2,亲测可用 QT-creator-...
react-redux-creator集成了react-router, react-redux, redux, redux-actions, redux-saga, seamless-immutable, connected-react-router, 简化了redux/异步处理和路由集成的配置工作,开箱即用使用redux常常需要...