首页 > 代码库 > [编织消息框架][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实现