系统架构

image.png
image.png

一些问题

程序入口:
image.png
@RpcScan给开发者用的,对于server侧,开发者在主启动类上标注这个,指定一个路径,框架就会去扫描这个路径及其子路径下的所有被@RpcService标注的类(即暴露的RPC实现类),将其加载到spring容器中:
image.png
那👆🏻代码为何不都直接都用@Component呢:1.开发者便于识别,看到@RpcService就知道这个bean与普通的@Component不一样,它是对外提供的RPC服务!;2.在spring初始化操作的过程中容易对该bean有一些特殊的操作,可将其发布到zookeeper中:
image.png

发布到zookeeper中的结果都存放在my-rpc根节点下面,格式为全类名+group+version:
rpc-guide - 图6

client调用远程服务时、server注册的时候,都需指定version和group,version区分迭代版本,group区分该接口的多个实现类。
image.png
image.png

再来看看这段代码,重点放在第一个方法的分析上:

  1. /**
  2. * call this method before creating the bean to see if the class is annotated
  3. *
  4. * @author shuang.kou
  5. * @createTime 2020年07月14日 16:42:00
  6. */
  7. @Slf4j
  8. @Component
  9. public class SpringBeanPostProcessor implements BeanPostProcessor {
  10. private final ServiceProvider serviceProvider;
  11. private final RpcRequestTransport rpcClient;
  12. public SpringBeanPostProcessor() {
  13. this.serviceProvider = SingletonFactory.getInstance(ZkServiceProviderImpl.class);
  14. this.rpcClient = ExtensionLoader.getExtensionLoader(RpcRequestTransport.class).getExtension("netty");
  15. }
  16. @SneakyThrows
  17. @Override
  18. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  19. if (bean.getClass().isAnnotationPresent(RpcService.class)) {
  20. log.info("[{}] is annotated with [{}]", bean.getClass().getName(), RpcService.class.getCanonicalName());
  21. // get RpcService annotation
  22. RpcService rpcService = bean.getClass().getAnnotation(RpcService.class);
  23. // build RpcServiceProperties
  24. RpcServiceConfig rpcServiceConfig = RpcServiceConfig.builder()
  25. .group(rpcService.group())
  26. .version(rpcService.version())
  27. .service(bean).build();
  28. serviceProvider.publishService(rpcServiceConfig);
  29. }
  30. return bean;
  31. }
  32. @Override
  33. public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
  34. Class<?> targetClass = bean.getClass();
  35. Field[] declaredFields = targetClass.getDeclaredFields();
  36. for (Field declaredField : declaredFields) {
  37. RpcReference rpcReference = declaredField.getAnnotation(RpcReference.class);
  38. if (rpcReference != null) {
  39. RpcServiceConfig rpcServiceConfig = RpcServiceConfig.builder()
  40. .group(rpcReference.group())
  41. .version(rpcReference.version()).build();
  42. RpcClientProxy rpcClientProxy = new RpcClientProxy(rpcClient, rpcServiceConfig);
  43. Object clientProxy = rpcClientProxy.getProxy(declaredField.getType());
  44. declaredField.setAccessible(true);
  45. try {
  46. declaredField.set(bean, clientProxy);
  47. } catch (IllegalAccessException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }
  52. return bean;
  53. }
  54. }

在分析第一个方法之前,可以先分析一下项目结构:此类属于rpc-framework-simple这个模块,也就是