[编织消息框架][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 }
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,先不考虑通信处理实现,在实现写框架过程,依赖越少实现越简单。所以每个实例对象构造出来时必须能正常工作
作者: | solq |
博客地址: | http://www.cnblogs.com/solq111 |
博客版权: | 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。 如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。 淘宝店: 海豚极货店 QQ群:9547527 |
如果你热爱生活、热爱编程、热爱吉他。扫一扫加我微信 |
我的新书《编织消息框架》目前进行中,感谢大家关注! |
本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。 |