[编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现
private static Map<Short, Map<Byte, Method>> RECEIVE_METHOD_INFO = new HashMap<>();
public static <T> T registerReceiveProxy(Object obj) {
Class<?> target = obj.getClass();
if (target.isInterface()) {
throw new RuntimeException("class is Interface : " + target);
}
QModel modelAnno = ReflectUtil.getAnno(target, QModel.class);
String proxyClassName = target.getCanonicalName() + "$$receive$$";
ClassPool classPool = JavassistHepler.classPool;
CtClass ctClass = classPool.makeClass(proxyClassName);
try {
// 设置接口,继承 target
CtClass[] interfaces = new CtClass[1];
interfaces[0] = classPool.get(IRpcReceive.class.getName());
ctClass.setInterfaces(interfaces);
ctClass.setSuperclass(JavassistHepler.getCtClass(target));
{
// 添加this字段
final String ctxName = target.getName();
CtField ctField = new CtField(classPool.get(ctxName), "_this", ctClass);
ctField.setModifiers(Modifier.PRIVATE | Modifier.FINAL);
// 添加json 忽略anno
ctField.getFieldInfo2().addAttribute(JavassistHepler.addAnno(JsonIgnore.class, ctClass));
ctClass.addField(ctField);
}
Map<Byte, Method> methods = new HashMap<>();
RECEIVE_METHOD_INFO.put(modelAnno.value(), methods);
// 生成代理方法
ReflectUtil.foreachMethods(target, (method) -> {
QCommond commond = method.getAnnotation(QCommond.class);
if (commond == null) {
return;
}
methods.put(commond.value(), method);
String resultType = "";
if (void.class != method.getReturnType()) {
resultType = " return ($r) ";
}
final String body = "{ " + resultType + "_this." + method.getName() + "($$); }";
JavassistHepler.addMethod(ctClass, method, body);
});
// 生成receive method
{
final String body = "{return ($r) " + QRpcFactory.class.getName() + ".proxyReceive(_this,$2, (short)" + modelAnno.value() + " ,(byte) $1);}";
JavassistHepler.addMethod(ctClass, RECEIVE_METHOD, body);
}
// 添加构造方法 new XXProxy(XX)
CtConstructor ctConstructor = new CtConstructor(JavassistHepler.toCtClassArray(target), ctClass);
ctConstructor.setBody("{ this._this = $1; }");
ctConstructor.setModifiers(Modifier.PUBLIC);
ctClass.addConstructor(ctConstructor);
Class<?> newClass = ctClass.toClass();
Constructor<T> constructor = (Constructor<T>) newClass.getConstructor(target);
constructor.setAccessible(true);
ctClass.detach();
Object ret = constructor.newInstance(obj);
RECEIVE.put(modelAnno.value(), (IRpcReceive) ret);
return (T) ret;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// 因为 javassist $$ 表达式访问的 参数类型 为 object 获取不到目标类型,所以只能用 invoke 处理
public static Object proxyReceive(Object target, Object[] args, short model, byte commondIndex) {
Map<Byte, Method> methods = RECEIVE_METHOD_INFO.get(model);
try {
return methods.get(commondIndex).invoke(target, args);
} catch (Exception e) {
throw new QRpcException(QCode.ENHANCE_ERROR_RPC_NOFIND_MODEL, "proxyReceive ", e);
}
}
}
@Test
public void testReceive() {
TestObject proxy = QRpcFactory.registerReceiveProxy(new TestObjectImpl()); proxy.a(1, "b");
proxy.setAge(30);
QResult<Integer> ret = proxy.getAge();
System.out.println(ret.getResult()); Object[] args = new Object[1];
args[0] =18; ((IRpcReceive) proxy).receive((byte) 2, args); ret = proxy.getAge();
System.out.println(ret.getResult());
args[0] = new TestObject1();
((IRpcReceive) proxy).receive((byte) 4, args);
} @Test
public void testObjectArgs() {
QRpcFactory.registerReceiveProxy(new TestObjectImpl());
IRpcReceive obj = QRpcFactory.loadReceiveProxy((short)1);
int a=30;
Integer b= 30;
double c=1d;
List<Integer> d = new ArrayList<>();
Integer[] e = new Integer[0];
Object[] args = new Object[5];
args[0] =a;
args[1] =b;
args[2] =c;
args[3] =d;
args[4] =e; obj.receive((byte)5, args);
}
在实际开发时 因为 javassist $$ 表达式访问的参数类型为object 获取不到目标类型,编译时出现错误
Type 'java/lang/Object' (current frame, stack[1]) is not assignable to integer
所以只能用 invoke 处理
[编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现的更多相关文章
- [编织消息框架][JAVA核心技术]动态代理介绍
由于java是种强类型静态语言,在执行时无法动态生成代码,静态语言基本都有这特性 动态生成代码有几种好处,也是弱类型语言的优点 1.部份逻辑可以实现热更新 2.远程调用实现非常适合 3.能动态生成扩展 ...
- [编织消息框架][JAVA核心技术]动态代理应用12-总结
动态代理这篇比较长,是框架组成的重要基础 回顾下学到的应用技术 1.异常应用 2.annotation技术 3.数值与逻辑分享 4.jdk.cglib.javassist等动态代理技术 5.懒处理.预 ...
- [编织消息框架][JAVA核心技术]动态代理应用4
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
- [编织消息框架][JAVA核心技术]动态代理应用7-IRpcSend实现
根据设计生成两个接口,IRpcSend send方法返回数据要求包装成QResult对象 public interface IRpcSend { public <T> QResult< ...
- [编织消息框架][JAVA核心技术]动态代理应用4-annotationProcessor
基础部份: 接下来讲编译JAVA时,生成自定义class 我们用 javax.annotation.processing.AbstractProcessor 来处理 public abstract c ...
- [编织消息框架][JAVA核心技术]动态代理应用2
接下来如何实现 第一步:先把服务类,调用方法转换成数字,方便传输 第二步:提取元信息,提取又有三种方式,三种各有优点,最优方式是第一种 1.编译java时处理 2.程序启动时处理,预处理 3.调用时处 ...
- [编织消息框架][JAVA核心技术]动态代理应用5-javassist
基础部份: 修改class我们用到javassist,在pom.xml添加 <properties> <javassist.version>3.18.2-GA</java ...
- [编织消息框架][JAVA核心技术]动态代理应用9-扫描class
之前介绍的annotationProcessor能在编译时生成自定义class,但有个缺点,只能每次添加/删除java文件才会执行,那天换了个人不清楚就坑大了 还记得之前介绍的编译时处理,懒处理,还有 ...
- [编织消息框架][JAVA核心技术]动态代理应用10-水平扩展方案
服务分为系统服务同用户服务两种 水平扩展是基于系统服务,而拆分方式又有几种方案,按数据跟业务情况来做决策 1.每个服务独立存储(图1):每个服务只负责一个或多个领域实体存储,A服务不能直接修改B服务的 ...
随机推荐
- 从C#到TypeScript - Reflect
总目录 从C#到TypeScript - 类型 从C#到TypeScript - 高级类型 从C#到TypeScript - 变量 从C#到TypeScript - 接口 从C#到TypeScript ...
- PHP会话控制Session与Cookie
理解会话控制的概念: 阅读过HTTP协议相关资料的同学都会知道HTTP协议是WEB服务器与客户端(浏览器)相互通信的协议,它是一种无状态协议,所谓无状态,指的是不会维护http请求数据,http请求是 ...
- (@WhiteTaken)UGUI中遇到的一些细碎的知识点
最近接触Unity中UGUI的知识比较多,遇到的东西,就慢慢积累下来吧.用到就不用去网上找了. 1.Unity加载Sprite图片资源.在Unity中,我们可能会遇到,一张图片中,有多个UI,这时候导 ...
- Eclipse标准版安装J2EE插件
WTP 使用Eclipse IDE for Java EE Developers是非常方便,但是太大,我喜欢按需配置.首先我们来了解什么是WTP. WTP(Web Tools Platform )项目 ...
- 抓包工具Wireshark的使用
WireShark是非常流行的网络封包分析软件,功能十分强大.可以截取各种网络封包,显示网络封包的详细信息. WireShark界面简介 启动WireShark的界面如下: 选择网卡 wireshar ...
- weui.css中flex容器下子项目的水平和垂直居中
想用weui.css写微信平台的页面,发现没有让flex(weui-flex)容器下,子项目(weui-flex__item)居中的类. 百度了一下,是用justify-content:center; ...
- C/C++学习路线图
文章转载自「开发者圆桌」一个关于开发者入门.进阶.踩坑的微信公众号 这里整理的C/C++学习路线图包含初中高三个部分,你可以通过百度云盘下载观看对应的视频 链接: http://pan.baidu.c ...
- 2017,科学使用strace神器(附代码,举栗子)
我感到惊讶,都2017年了,几乎没有人知道他们可以使用strace的了解所有事情.它总是我拔出的第一个调试工具之一,因为它通常在我运行的Linux系统上可用,并且它可以用于解决各种各样的问题. 什么是 ...
- WeMall微信商城源码插件大转盘代码详情
WeMall微信商城源码插件大转盘代码是用于商业推广的比较有效的方式,分享了部分比较重要的代码,供技术员学习参考 代码详情地址:http://addon.wemallshop.com/Product/ ...
- app 评分
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #822e0e } p.p2 { margin: 0.0px 0. ...