[编织消息框架][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,先不考虑通信处理实现,在实现写框架过程,依赖越少实现越简单。所以每个实例对象构造出来时必须能正常工作

时间: 2024-10-10 04:32:58

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

[编织消息框架][JAVA核心技术]动态代理介绍

由于java是种强类型静态语言,在执行时无法动态生成代码,静态语言基本都有这特性 动态生成代码有几种好处,也是弱类型语言的优点 1.部份逻辑可以实现热更新 2.远程调用实现非常适合 3.能动态生成扩展类,屏蔽复杂性,在原来基础上扩展功能,无破坏源码特性 静态语言也不是没有方案去解决,解决方案很多. 其中嵌入一个脚本引擎语言,就能弥补,还有动态代理技术 jdk 自带的动态代理是一种解决方案 cglib动态代理 spring默认使用 javassit 能在执行期修改class 顺便说下scala语言

[编织消息框架][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 Ru

[编织消息框架][JAVA核心技术]动态代理应用2

接下来如何实现 第一步:先把服务类,调用方法转换成数字,方便传输 第二步:提取元信息,提取又有三种方式,三种各有优点,最优方式是第一种 1.编译java时处理 2.程序启动时处理,预处理 3.调用时处理,懒处理 第三步:编码解释 第四步:请求方式 第五步:分布式支持 第一步: @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface QModel { short value(); } @Targ

[编织消息框架][JAVA核心技术]动态代理应用9-扫描class

之前介绍的annotationProcessor能在编译时生成自定义class,但有个缺点,只能每次添加/删除java文件才会执行,那天换了个人不清楚就坑大了 还记得之前介绍的编译时处理,懒处理,还有个预处理没介绍对吧 预处理:应用程序启动前做的处理,如setup 扫描class处理 1.从ClassLoader 和 System.getProperty("java.class.path") 读取所有classPath 2.解释每个classPath ,用正则匹配jar/class 文

[编织消息框架][JAVA核心技术]动态代理应用3

我们先使用懒处理实现提取接口类上的元信息: public abstract class QRpcFactory { public static <T> T loadProxy(Class<T> target, QNode... nodes) public static <T> T loadProxy(Class<T> target, long... ids) } 通过工厂类绑定session id 或 node 生成代理实例 RpcContext 是处理临时

[编织消息框架][JAVA核心技术]异常基础

Java异常体系结构 Thorwable类所有异常和错误的超类,有两个子类Error和Exception,分别表示错误和异常. 其中异常类Exception又分为运行时异常(RuntimeException)和编译时异常(checked Exception), 下面将详细讲述这些异常之间的区别与联系: 1.Error与Exception Error是程序无法处理的错误,比如OutOfMemoryError.ThreadDeath等.这些异常发生时, Java虚拟机(JVM)一般会选择线程终止.

代理模式 &amp; Java原生动态代理技术 &amp; CGLib动态代理技术

第一部分.代理模式  代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息.过滤消息.把消息转发给委托类,以及事后处理消息等.代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务.(其实就是在代理类中关联一个委托类的实例,然后在代理类中进行包装). UML图如下: 第二部分.在Java中实现代理模式  按照代理的创建时期,代理类可以分

java的动态代理

最近在研究这个java的ssh三大框架,当看到这个spring的aop(aspect-orinted-programming)的时候,其中提到了这个java的动态代理机制,这个动态代理,我以前似乎看过,但是那是设计模式的事情.所以有一次搜索到这个动态代理,对这个动态代理进行一个研究,记录自己的进步. spring的aop编程是一个面向切面的编程思想,和这个面向对象的编程是一个补充的关系,不是一个对立的关系.面向对象强调和使用的从上到下的层次关系,但是aop编程使用的是从左到右的关系.一个是纵的关

java中动态代理实现机制

JAVA各种动态代理实现的比较 接口 interface AddInterface{ int add(int a, int b); } interface SubInterface{ int sub(int a, int b); } 实现类 class Arithmetic implements AddInterface, SubInterface{ @Override public int sub(int a, int b) { return a-b; } @Override public i