[编织消息框架][JAVA核心技术]动态代理应用7-实现设计
Posted solq321
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[编织消息框架][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 }
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 }
测试理论:
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-实现设计的主要内容,如果未能解决你的问题,请参考以下文章
[编织消息框架][JAVA核心技术]动态代理应用8-IRpcReceive实现