消费端启动过程分析
1 触发服务引用过程
消费端的启动过程中,对服务引用由ReferenceBean类开始处理逻辑,该类继承了<dubbo:reference>标签对应的配置类ReferenceConfig,还实现了一系列Spring接口用于参与Spring容器的启动以及bean的创建过程中去。ServiceBean类实现了InitializingBean接口的afterPropertiesSet方法。
对于注解方式引用服务,首先在在Spring回调AnnotationBean类的postProcessBeforeInitialization方法时,触发调用ReferenceBean. afterPropertiesSet ()方法,若引用服务的注解属性init设置为true,则在Spring的初始化过程中进行初始化引用服务,否则等到应用注入或引用实例时再初始化,在Spring中初始化时通过ReferenceBean.getObject() 间接调用ReferenceConfig.get() 方法完成引用服务的初始化。
对于XML方式引用服务,在spring的容器ApplicationConetext的启动过程refesh过程中最后第二步会预先初始化单例bean,在bean的初始化过程中会设置beanName,设置容器的appliactionContext并回调afterPropertiesSet方法,若此引用服务设置为立即初始化,则通过ReferenceBean.getObject() 间接调用ReferenceConfig.get() 方法完成引用服务的初始化。
上述设置服务引用延迟的方法是配置<dubbo:reference>标签的init属性。
2 检查点对点直连配置
配置点对点直连的方式有三种,分别如下:
1、在<dubbo:reference>中配置url指向提供者,将绕过注册中心,多个地址用分号隔开;
2、在JVM启动参数中加入-D参数映射服务地址,key为服务名,value为服务提供者url;
例如:java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890
3、如果服务比较多,也可以用文件映射,用-Ddubbo.resolve.file指定映射文件路径,例如:java -Ddubbo.resolve.file=xxx.properties
然后在映射文件xxx.properties中加入:(key为服务名,value为服务提供者url),
例如:com.alibaba.xxx.XxxService=dubbo://localhost:20890
在ReferenceConfig.init()方法中,首先通过第2种方式获取服务地址,若没有配置再通过第3种方式获取服务地址,在第3种方式中优先获取${user.home}/dubbo-resolve.properties文件,若没有在使用-Ddubbo.resolve.file指定的映射文件,最后在前两种方法均没有获取到服务地址的情况下,取第1种方式中配置的服务地址。
3 检查是否引用本地服务
配置是否引用本地服务的方式有如下5种,按照以下5种方式顺序检查是否引用本地服务。
1、配置<dubbo:reference injvm="true".../>,injvm为true表示引用本地服务;为false表示引起远程服务;
2、配置<dubbo:protocol name="injvm"… />,name为injvm表示引用本地服务;
3、配置<dubbo:reference...scope="remote"/>,scope为remote表示引用远程服务;为local表示引用本地服务;
4、配置<<dubbo:referencegeneric =”true”…>,generic为false表示引用本地服务,为true表示引用远程服务,默认为false。
5、检查本地是否有服务暴露,有则引用本地服务。
4 引用服务
4.1 本地引用服务
代理工厂类Protocol$Adpative根据URL中的protocol选择InjvmProtocol来处理本地引用,所有Protocol类均被ProtocolFilterWrapper、ProtocolListenerWrapper封装。
首先调用InjvmProtocol.refer()方法,把服务转换成Invoker,即初始化InjvmInvoker对象;