动态代理屏蔽网络传输细节

我们在前面的章节讲到过我们需要用到动态代理来屏蔽复杂的网络传输细节。对应的代码: RpcClientProxy.java

  1. @Slf4j
  2. public class RpcClientProxy implements InvocationHandler {
  3. public <T> T getProxy(Class<T> clazz) {
  4. return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
  5. }
  6. @Override
  7. public Object invoke(Object proxy, Method method, Object[] args) {
  8. }
  9. }

当我们去调用一个远程的方法的时候,实际上是通过代理对象调用的。

获取代理对象的方法如下:

  1. public <T> T getProxy(Class<T> clazz) {
  2. return (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class<?>[]{clazz}, this);
  3. }

网络传输细节都被封装在了 invoke() 方法中。

  1. public Object invoke(Object proxy, Method method, Object[] args) {
  2. log.info("invoked method: [{}]", method.getName());
  3. RpcRequest rpcRequest = RpcRequest.builder().methodName(method.getName())
  4. .parameters(args)
  5. .interfaceName(method.getDeclaringClass().getName())
  6. .paramTypes(method.getParameterTypes())
  7. .requestId(UUID.randomUUID().toString())
  8. .group(rpcServiceProperties.getGroup())
  9. .version(rpcServiceProperties.getVersion())
  10. .build();
  11. RpcResponse<Object> rpcResponse = null;
  12. if (rpcRequestTransport instanceof NettyRpcClient) {
  13. CompletableFuture<RpcResponse<Object>> completableFuture = (CompletableFuture<RpcResponse<Object>>) rpcRequestTransport.sendRpcRequest(rpcRequest);
  14. rpcResponse = completableFuture.get();
  15. }
  16. if (rpcRequestTransport instanceof SocketRpcClient) {
  17. rpcResponse = (RpcResponse<Object>) rpcRequestTransport.sendRpcRequest(rpcRequest);
  18. }
  19. this.check(rpcResponse, rpcRequest);
  20. return rpcResponse.getData();
  21. }

通过注解注册/消费服务

我们这里借用了 Spring 容器相关的功能。核心代码都放在了 : src/main/java/github/javaguide/spring 包下面。

我们定义两个注解:
●RcpService :注册服务
●RpcReference :消费服务

RcpService.java

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target({ElementType.TYPE})
  4. @Inherited
  5. public @interface RpcService {
  6. /**
  7. * Service version, default value is empty string
  8. */
  9. String version() default "";
  10. /**
  11. * Service group, default value is empty string
  12. */
  13. String group() default "";
  14. }

RpcReference.java

  1. @Documented
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Target({ElementType.FIELD})
  4. @Inherited
  5. public @interface RpcReference {
  6. /**
  7. * Service version, default value is empty string
  8. */
  9. String version() default "";
  10. /**
  11. * Service group, default value is empty string
  12. */
  13. String group() default "";
  14. }

简单说一下原理。

我们实现需要 BeanPostProcessor 接口并重写 postProcessBeforeInitialization()方法和 postProcessAfterInitialization() 方法。

Spring bean 在实例化之前会调用 postProcessBeforeInitialization()方法,在 Spring bean 实例化之后会调用 postProcessAfterInitialization() 方法。

  1. @Slf4j
  2. @Component
  3. public class SpringBeanPostProcessor implements BeanPostProcessor {
  4. @Override
  5. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  6. }
  7. @Override
  8. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  9. }
  10. }

被我们使用 RpcService和RpcReference 注解的类都算是 Spring Bean。

●我们可以在postProcessBeforeInitialization()方法中去判断类上是否有RpcService 注解。如果有的话,就取出 group 和 version 的值。然后,再调用 ServiceProvider 的 publishService() 方法发布服务即可!
●我们可以在 postProcessAfterInitialization() 方法中遍历类的属性上是否有 RpcReference 注解。如果有的话,我们就通过反射将这个属性赋值即可!

https://segmentfault.com/a/1190000039821699