首页 > 代码库 > [编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现
[编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现
1 private static Map<Short, Map<Byte, Method>> RECEIVE_METHOD_INFO = new HashMap<>(); 2 3 public static <T> T registerReceiveProxy(Object obj) { 4 Class<?> target = obj.getClass(); 5 if (target.isInterface()) { 6 throw new RuntimeException("class is Interface : " + target); 7 } 8 QModel modelAnno = ReflectUtil.getAnno(target, QModel.class); 9 String proxyClassName = target.getCanonicalName() + "$$receive$$";10 ClassPool classPool = JavassistHepler.classPool;11 CtClass ctClass = classPool.makeClass(proxyClassName);12 13 try {14 // 设置接口,继承 target15 CtClass[] interfaces = new CtClass[1];16 interfaces[0] = classPool.get(IRpcReceive.class.getName());17 ctClass.setInterfaces(interfaces);18 ctClass.setSuperclass(JavassistHepler.getCtClass(target));19 {20 // 添加this字段21 final String ctxName = target.getName();22 CtField ctField = new CtField(classPool.get(ctxName), "_this", ctClass);23 ctField.setModifiers(Modifier.PRIVATE | Modifier.FINAL);24 // 添加json 忽略anno25 ctField.getFieldInfo2().addAttribute(JavassistHepler.addAnno(JsonIgnore.class, ctClass));26 ctClass.addField(ctField);27 }28 29 Map<Byte, Method> methods = new HashMap<>();30 RECEIVE_METHOD_INFO.put(modelAnno.value(), methods);31 32 // 生成代理方法33 ReflectUtil.foreachMethods(target, (method) -> {34 QCommond commond = method.getAnnotation(QCommond.class);35 if (commond == null) {36 return;37 }38 methods.put(commond.value(), method);39 String resultType = "";40 if (void.class != method.getReturnType()) {41 resultType = " return ($r) ";42 }43 final String body = "{ " + resultType + "_this." + method.getName() + "($$); }";44 JavassistHepler.addMethod(ctClass, method, body);45 });46 47 // 生成receive method48 {49 final String body = "{return ($r) " + QRpcFactory.class.getName() + ".proxyReceive(_this,$2, (short)" + modelAnno.value() + " ,(byte) $1);}";50 JavassistHepler.addMethod(ctClass, RECEIVE_METHOD, body);51 }52 53 // 添加构造方法 new XXProxy(XX)54 CtConstructor ctConstructor = new CtConstructor(JavassistHepler.toCtClassArray(target), ctClass);55 ctConstructor.setBody("{ this._this = $1; }");56 ctConstructor.setModifiers(Modifier.PUBLIC);57 ctClass.addConstructor(ctConstructor);58 Class<?> newClass = ctClass.toClass();59 Constructor<T> constructor = (Constructor<T>) newClass.getConstructor(target);60 constructor.setAccessible(true);61 ctClass.detach();62 Object ret = constructor.newInstance(obj);63 RECEIVE.put(modelAnno.value(), (IRpcReceive) ret);64 return (T) ret;65 } catch (Exception e) {66 throw new RuntimeException(e);67 }68 }69 70 // 因为 javassist $$ 表达式访问的 参数类型 为 object 获取不到目标类型,所以只能用 invoke 处理71 public static Object proxyReceive(Object target, Object[] args, short model, byte commondIndex) {72 Map<Byte, Method> methods = RECEIVE_METHOD_INFO.get(model);73 try {74 return methods.get(commondIndex).invoke(target, args);75 } catch (Exception e) {76 throw new QRpcException(QCode.ENHANCE_ERROR_RPC_NOFIND_MODEL, "proxyReceive ", e);77 }78 }79 }
@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实现
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。