大致思路:
我们都知道spring中在用dubbo的时候主要靠@service和@reference注解,那么主要讲解这两个注解的原理
spring容器在加载的时候 我们需要扫描@service的类 ,往spring容器中放一个bean,还要创建一个dubbo的serviceBean
serviceBean有各种属性 比如version ,register等等
这个对象中有一个export方法 这个方法就是用来服务导出及服务注册
serviceBean和 bean对象 有一个关联 通过ref属性指向
一. @Enable注解有下面两个注解
1. @EnableDubboConfig
这个注解用来加载配置 @Import一个类DubboConfigConfigurationRegistrar 实现了一个 ImportBeanDefinitionRegistrar类 如果实现了这个类 那么spring在启动的时候就会执行这个类中的方法
这个方法主要是 往spring容器中添加bean
1) 处理properties文件
spring会读取这个文件 会放在enviroment对象里面 然后dubbo从这个对象中取就行了
2) 生成不同的配置对象
根据 dubbo.application.* 等属性 生成 ApplicationConfig对象
根据 dubbo.protocols.* 等属性 生成 ProtocolConfig对象
根据 dubbo.registers.*等属性 生成 RegistryConfig 对象
providerConfig,ConfigCenterConfig,ConsumerConfig等
这些对象会作为ServiceBean对象的属性
Single Multiple 这个两个类主要是描述配置前缀对应哪个类 比如 dubbo.application前缀对应ApplicationConfig.class
这两个类上面都有一个注解@EnableDubboConfigBingdings 对应 DubboConfigBingdingsRegistrar类
spring启动的时候会调用这个类的方法,这个方法会去哪这个注解里面的子注解 就能拿到那些前缀和类的关系
通过前缀到environment去拿那些配置项 如果是空的直接return 如果有了就生成beanNames,因为这块代码是复用的,所以是Names,如果type为single就返回只有一个值的集合
通过字符串截取操作得到beanNames 遍历这些beanNames,1. 往spring容器中注册bean 2. 给刚才生成的bean对象中的属性赋值
AutowiredBeanPostProcessor作用 所有的bean都会经过这个类 给bean中的@Autowired注解的属性赋值 注意:dubbo2.5版本每一个bean生成一个processor 实际所有bean走同一个processor即可 新版本dubbo解决了这个问题
目前一个bean会经过所有的processor 然后通过beanName判断来处理对应的bean 这点就是没必要的
经过DubboConfigBinder.bind方法猴 ApplicationConfig类的属性都有值 通过前缀获取enviroment中所有配置值 然后赋值给对应的属性
2. @EnableComponentScan
这个注解用来进行扫描配置的路径 并且来处理@Service @Reference注解
1) 处理@Service注解:
ServiceAnnotationBeanPostProcessor是一个bean工厂的处理类 不是 bean的后置处理类 与上面的AutowireBeanPostProcessor类不一样 它的作用是注册bean 被@Service注解标记的类
首先定义一个扫描器 会扫描某个类上面有没有@Service注解
会放在spring容器中registry
然后注册 serviceBean 先拿到注解 然后拿到服务类对应的service实现类的名字
去构造一个ServiceBean 然后拿@service上的属性值赋值给这个 ServiceBean 这里会忽略一些值 如果protocol 赋值的时候是一个字符串 比如 p1 所以不会将这个 字符串赋值到ServiceBean属性上 而是通过前面加载的配置类找到
bean对象 赋值到属性上
所以这些忽略的属性值 下面要单独配置 addPropertyReference 这个方法就是通过name找到对应的bean赋值到ServiceBean对应的属性中 这是spring中的一个方法
2) 处理@Reference注解
这个注解同@Autowired注解 所以我们也需要一个ReferenceBeanPostProcessor后置类处理所有带有@Refere注解的属性
doGetInjectedBean() 这个方法对应spring容器中postProcessPropertyValues 通过了解spring中的bean的生命周期就能明白这一点
传入一个bean 就会遍历这个类的所有field 找到带有@Reference注解的fields
InjectionMetadata表示注入点 一个bean中的可能会有多个注入点 这个是spring的一个接口 dubbo中有其对应的两个实现类 一个判断field上有没有@Reference注解 一个是个判读method上有没有@Reference注解
他们分别会放在两个不同的list中 然后遍历 找到注入点后 对当前注入点进行赋值
需要 注解上的属性 当前类 类名称 注入点类型 注入点元素
然后调用 doGetInjectedBean方法生成一个对象 这个方法先用ServiceBean的名字去当前spring容器中找有没有对应的ServiceBean 这个ServiceBean命名是 ServiceBean:org.apche.demo.DemoService
ServiceBeanNameBuider.build()来构建这个名字 如果有这个名字 就生成一个代理对象 这里为啥不返回ref对应的bean对象 但是这里是dubbo 只能给一个代理对象 这样dubbo里面的很多逻辑才能走到 这里并不是@Autowired注解
接下来又会用@Reference中的属性比如group version 生成一个bean 这里会缓存起来 这个key是@Reference及其属性值组成的字符串 value为 ReferenceBean
ReferenceBean表示我们引入的dubbo服务 这个类中有一个get方法用来产生代理对象
这里会判断referenceBean是否在spring容器中 如果没有就会将这个bean放到spring容器中 它是一个FactoryBean 为了支持@Autowired注解
构建映射关系,如果缓存中没有就返回代理对象 执行invoke方法
这里最重要的是有一个缓存 而且@Reference我们得到的一个消费者代理对象
最后注意ReferenceBeanPostProcessor的执行在AutowiredBeanPostProcessor前面
3. 下图就是整个@EnableDubbo注解的源码流程图,也是spring整合dubbo的核心逻辑: