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

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

public interface IRpcSend {
    public <T> QResult<T> send(byte command, Object... args);
}
public interface IRpcReceive {
    public <T> T receive(byte command, Objec[] 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 public static void registerSendProxy(Class<?> target) {
 2     if (!target.isInterface()) {
 3         throw new RuntimeException("class is not  Interface : " + target);
 4     }
 5     QModel modelAnno = ReflectUtil.getAnno(target, QModel.class);
 6     String proxyClassName = target.getCanonicalName() + "$$send$$";
 7     ClassPool classPool = JavassistHepler.classPool;
 8     CtClass ctClass = classPool.makeClass(proxyClassName);
 9 
10     try {
11         // 设置接口
12         CtClass[] interfaces = new CtClass[3];
13         interfaces[0] = classPool.get(target.getName());
14         interfaces[1] = classPool.get(IRpcSend.class.getName());
15         interfaces[2] = classPool.get(IRpcContext.class.getName());
16         ctClass.setInterfaces(interfaces);
17 
18         {
19             // 添加ctx字段
20             final String ctxName = RpcContext.class.getName();
21             CtField ctField = new CtField(classPool.get(ctxName), "ctx", ctClass);
22             ctField.setModifiers(Modifier.PRIVATE);
23             ctClass.addField(ctField);
24             // 添加ctx get set 方法
25             CtMethod ctMethod = CtMethod.make("public " + ctxName + " getContext(){return ctx;}", ctClass);
26             ctMethod.setModifiers(Modifier.PUBLIC);
27             ctClass.addMethod(ctMethod);
28 
29             ctMethod = CtMethod.make("public void setContext(" + ctxName + " value){ ctx =value;}", ctClass);
30             ctMethod.setModifiers(Modifier.PUBLIC);
31             ctClass.addMethod(ctMethod);
32         }
33 
34         // 生成send method 调用静态方法减少书写复杂
35         {
36           37            38             final String body = " return ($r){ " + resultType + QRpcFactory.class.getName() + ".proxySend(this,$2, (short)" + modelAnno.value() + "  ,(byte) $1);}";
39             JavassistHepler.addMethod(ctClass, SEND_METHOD, body);
40         }
41 
42         // 生成代理方法
43         for (Method method : target.getDeclaredMethods()) {
44             QCommond commond = method.getAnnotation(QCommond.class);
45             if (commond == null) {
46                 continue;
47             }
48 
49             String resultType = "";
50             if (void.class != method.getReturnType()) {
51                 resultType = " return ($r) ";
52             }
53             final String body = "{ " + resultType + " this.send((byte)" + commond.value() + ",$args); }";
54             JavassistHepler.addMethod(ctClass, method, body);
55         }
56 
57         // 保存记录
58         Class<?> newClass = ctClass.toClass();
59         ctClass.detach();
60         SEND_CLASS.put(modelAnno.value(), newClass);
61 
62     } catch (Exception e) {
63         e.printStackTrace();
64     }
65 }
66 public static QResult proxySend(IRpcContext target, Object[] args, short model, byte commondIndex) {
67     System.out.println("model : " + model + " commondIndex : " + commondIndex);
68     return null;
69 }

 

测试理论:

    @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();

        @QCommond(4)
        public void setObj(TestObject1 obj);
        
        @QCommond(5)
        public void test(int a,Integer b,Double c ,List<Integer> d,Integer[] e );
    }

    public class TestObject1 {
        public int a = 67;
    }

    public static class TestObjectImpl implements TestObject {
        private int age;

        @Override
        public void a(int a, String b) {
            System.out.println("a : " + a + " " + b);
        }

        @Override
        public void setAge(int value) {
            age = value;
        }

        @Override
        public QResult<Integer> getAge() {
            return QResultWrapper.of(age);
        }

        @Override
        public void setObj(TestObject1 obj) {
            System.out.println(obj.a);
        }

        @Override
        public void test(int a, Integer b, Double c ,List<Integer> d,Integer[] e ) {
            
        }
    }

 

 public class TestRpcProxy {
     @Test
     public void testSend() {
         QRpcFactory3.registerSendProxy(TestObject.class);
         TestObject proxy = QRpcFactory3.loadSendProxy(TestObject.class, 1L);
 
         proxy.a(1, "b");
         QResult<Integer> ret = proxy.getAge();
     }
 }

 

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

 

posted @ 2017-04-10 13:26  solq321  阅读(332)  评论(0编辑  收藏  举报