首页 > 代码库 > [编织消息框架][JAVA核心技术]动态代理应用7-实现设计

[编织消息框架][JAVA核心技术]动态代理应用7-实现设计

根据设计生成两个接口,IRpcSend send方法返回数据要求包装成QResult对象

public interface IRpcSend {    public <T> QResult<T> send(byte command, Object... args);}
public interface IRpcReceive {    public <T> T receive(byte command, Object... args);}
public interface IRpcContext {    RpcContext getContext();    void setContext(RpcContext ctx);}
public interface QResult<T> extends Future<T> {    /**     * 是否出错     * */    public boolean isError();    /**     * 获取返回结果     * */       public T getResult();    /**     * 设置结果     * */      public void setResult(T result);}
技术分享
 1 @SuppressWarnings("unchecked") 2 public abstract class QRpcFactory { 3     private static Method SEND_METHOD = ReflectUtil.getMethod(IRpcSend.class, "send"); 4     private static Method RECEIVE_METHOD = ReflectUtil.getMethod(IRpcReceive.class, "receive"); 5  6     private static Map<Short, Class<?>> SEND_CLASS = new HashMap<>(); 7     private static Map<Short, IRpcReceive> RECEIVE = new HashMap<>(); 8  9     public static <T> T loadSendProxy(Class<T> target, QNode... nodes) {10         T ret = loadSendPorxy0(target);11         IRpcContext ctx = (IRpcContext) ret;12         ctx.setContext(RpcContext.of(nodes));13         return ret;14     }15 16     public static <T> T loadSendProxy(Class<T> target, Long... ids) {17     T ret = loadSendPorxy0(target);18     IRpcContext ctx = (IRpcContext) ret;19     ctx.setContext(RpcContext.of(ids));20     return ret;21     }22 23     public static <T> T loadSendProxy(Class<T> target, String... addresses) {24         T ret = loadSendPorxy0(target);25         IRpcContext ctx = (IRpcContext) ret;26         ctx.setContext(RpcContext.of(addresses));27         return ret;28     }29 30     private static <T> T loadSendPorxy0(Class<T> target) {31         QModel modelAnno = ReflectUtil.getAnno(target, QModel.class);32         Class<?> proxyClass = SEND_CLASS.get(modelAnno.value());33         T ret = null;34         try {35             ret = (T) proxyClass.newInstance();36         } catch (InstantiationException | IllegalAccessException e) {37             throw new RuntimeException(e);38         }39         return ret;40     }41 42     public static <T> T loadLocalProxy(Class<T> target) {43         QModel modelAnno = ReflectUtil.getAnno(target, QModel.class);44         Object ret = RECEIVE.get(modelAnno.value());45         return (T) ret;46     }47 48     public static IRpcReceive loadReceiveProxy(short model) {49         IRpcReceive ret = RECEIVE.get(model);50         return ret;51     }52 }
QRpcFactory
技术分享
 1  // register 2     public static void registerSendProxy(Class<?> target) { 3     if (!target.isInterface()) { 4         throw new RuntimeException("class is not  Interface : " + target); 5     } 6     QModel modelAnno = ReflectUtil.getAnno(target, QModel.class); 7     String proxyClassName = target.getCanonicalName() + "$$$$"; 8     ClassPool classPool = JavassistHepler.classPool; 9     CtClass ctClass = classPool.makeClass(proxyClassName);10 11     try {12         // 设置接口13         CtClass[] interfaces = new CtClass[3];14         interfaces[0] = classPool.get(target.getName());15         interfaces[1] = classPool.get(IRpcSend.class.getName());16         interfaces[2] = classPool.get(IRpcContext.class.getName());17         ctClass.setInterfaces(interfaces);18 19         {20         // 添加ctx字段21         final String ctxName = RpcContext.class.getName();22         CtField ctField = new CtField(classPool.get(ctxName), "ctx", ctClass);23         ctField.setModifiers(Modifier.PRIVATE);24         ctClass.addField(ctField);25         // 添加ctx get set 方法26         CtMethod ctMethod = CtMethod.make("public " + ctxName + " getContext(){return ctx;}", ctClass);27         ctMethod.setModifiers(Modifier.PUBLIC);28         ctClass.addMethod(ctMethod);29 30         ctMethod = CtMethod.make("public void setContext(" + ctxName + " value){ ctx =value;}", ctClass);31         ctMethod.setModifiers(Modifier.PUBLIC);32         ctClass.addMethod(ctMethod);33         }34 35         // 生成send method 调用静态方法减少书写复杂36         {37         Method method = SEND_METHOD;38         String resultType = " return ($r)";39         final String body = "{ " + resultType + QRpcFactory3.class.getName() + ".proxy(this,$args, (short)" + modelAnno.value() + "  ,(byte) $1);}";40 41         Class<?> returnType = method.getReturnType();42         CtMethod ctMethod = new CtMethod(classPool.get(returnType.getName()), method.getName(), JavassistHepler.toCtClassArray(method.getParameterTypes()), ctClass);43         ctMethod.setModifiers(method.getModifiers());44         ctMethod.setBody(body);45         ctClass.addMethod(ctMethod);46         }47 48         // 生成代理方法49         Map<Byte, String> methodMap = new HashMap<>();50         for (Method method : target.getDeclaredMethods()) {51         QCommond commond = method.getAnnotation(QCommond.class);52         if (commond == null) {53             continue;54         }55         methodMap.put(commond.value(), method.getName());56 57         String resultType = "";58         if (void.class != method.getReturnType()) {59             resultType = " return ($r) ";60         }61         final String body = "{ " + resultType + " this.send((byte)" + commond.value() + ",$args); }";62         Class<?> returnType = method.getReturnType();63         CtMethod ctMethod = new CtMethod(classPool.get(returnType.getName()), method.getName(), JavassistHepler.toCtClassArray(method.getParameterTypes()), ctClass);64         ctMethod.setModifiers(method.getModifiers());65         ctMethod.setBody(body);66         ctClass.addMethod(ctMethod);67         }68 69         // 保存记录70         Class<?> ret = ctClass.toClass();71         ctClass.detach();72         SEND_CLASS.put(modelAnno.value(), ret);73 74     } catch (Exception e) {75         e.printStackTrace();76     }77     }78 79     public static QResult proxy(IRpcContext target, Object[] args, short model, byte commondIndex) {80     System.out.println("model : " + model + " commondIndex : " + commondIndex);81     return null;82     }
registerSendProxy

 测试理论:

public class TestRpcSendProxy {    @QModel(1)    public interface TestObject {        @QCommond(1)        public void a(int a, String b);        @QCommond(2)        public void setAge(int value);        @QCommond(3)        public QResult<Integer> getAge();    }    public static void main(String[] args) {        QRpcFactory3.registerSendProxy(TestObject.class);        TestObject proxy = QRpcFactory.loadSendProxy(TestObject.class, 1L);        proxy.a(1, "b");        QResult<Integer> ret = proxy.getAge();    }}

由于发送处理涉及netty,先不考虑通信处理实现,在实现写框架过程,依赖越少实现越简单。所以每个实例对象构造出来时必须能正常工作

 

[编织消息框架][JAVA核心技术]动态代理应用7-实现设计