Dubbo source code analysis

1. First understand the common configuration of dubbo

<dubbo:service/> Service configuration, used to expose a service, define the meta information of the service, a service can be exposed by multiple protocols, and a service can also be registered with multiple registries.

例子<dubbo:service ref="helloServiceDubbo" interface="com.dubbozone.service.dubbo.HelloServiceDubbo" version="1.0.0" protocol="http" path="api/hello" timeout="60000" />

 

<dubbo:reference/> Reference service configuration, used to create a remote service proxy, a reference can point to multiple registries.

例子<dubbo:reference ref="helloServiceDubbo" interface="com.dubbozone.service.dubbo.HelloServiceDubbo" />

 

The <dubbo:protocol/> protocol configuration is used to configure the protocol information for providing services. The protocol is specified by the provider and passively accepted by the consumer.

例子<dubbo:protocol host="${dubboHost}" name="http" port="${dubboPort}" server="servlet" contextpath="${dubboContextpath}" />

 

<dubbo:application/> Application configuration, used to configure the current application information, whether the application is a provider or a consumer.

例子<dubbo:application name="member"/> 

 

<dubbo:module/> Module configuration, used to configure the current module information, optional.

 

<dubbo:registry/> Registry configuration, used to configure information about connecting to the registry.

例子<dubbo:registry protocol="zookeeper" address="${zk.ip}" />

 

<dubbo:monitor/> Monitoring center configuration, used to configure information about connecting to the monitoring center, optional.

例子<dubbo:monitor protocol="registry" />

 

<dubbo:provider/> The default value of the provider. When a certain property of ProtocolConfig and ServiceConfig is not configured, this default value is used. It is optional.

例子<dubbo:provider timeout="60000" retries="0" loadbalance="random" />

 

<dubbo:consumer/> The default configuration of the consumer. When a property of ReferenceConfig is not configured, this default value is used, which is optional.

例子<dubbo:consumer timeout="60000" check="false" />

 There are other properties, you can go to the dubbo official website to view

http://dubbo.apache.org/books/dubbo-user-book/references/xml/introduction.html

 

 

2. Understand how spring recognizes dubbo

后面会结合官网提供的暴露服务时序图来对dubbo服务进行一个讲解,今天先讲一个spring是怎么实现跟dubbo结合的,dubbo是什么时候触发export方法然后暴露服务的。

 

基于tomcat来分析dubbo的暴露服务

启动tomcat,在spring 容器启动时,会读取dubbo的配置文件,dubbo的配置如下


各个配置的含义上面已经介绍。

在spring加载dubbo配置文件前,先简单了解下spring的bean初始化机制:Spring的InitializingBean接口有很好的用处,位于spring beans中,它只提供一个方法afterPropertiesSet(),当你实现了该方法后,spring就会对你提供框架级的支持:当你通过sring容器生产出实现了该接口的类的实例后,它就会调用afterPropertiesSet方法,通过这个方法,你可以检查你的bean是否正确地被初始化了.当然,你也可以用init-method方法.这两种方式可以同时使用,调用的顺序为init-method后调用。

 

Spring读取配置文件,关键是dubbo:service标签,每个dubbo:service标签都对应一个ServiceBean实例。

 

来看下ServiceBean.java.这个类的定义

public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener<ContextRefreshedEvent>, BeanNameAware {...}

 

这里有个关键地方:ApplicationContextAware和InitializingBean以及ApplicationListener(注意:下面三个步骤是在容器初始化的时候是按顺序来的)

1.实现了ApplicationContextAware类的setApplicationContext方法。把spring的上下文applicationContext赋给当前类中的变量,同时维护到dubbo中,通过反射调用AbstractApplicationContext.addApplicationListener方法,把当前servicebean对象作为listener添加到abstractapplicationContext中,并标记supportedApplicationListener为true。

 

2.ServiceBean实现了Spring提供的接口InitializingBean。当在完成Bean初始化和注入的时候程序会自动执行InitializingBean接口中的afterPropertiesSet方法(配置了几个dubbo:service,就会执行几次改方法,因为初始化与之匹配的servicebean)。在这个方法里面会对provider、application、module、registries、moniter、protocols、path等进行初始化。

如果没有设置延迟加载,则不会执行export()

if (! isDelay()) {

export();

}

也就是说并没有在此时进行服务暴漏。

 

3.实现了ApplicationListener接口的onApplicationEvent方法。ApplicationContext在运行期会自动检测到所有实现了ApplicationListener的bean对象,并将其作为事件接收对象,由此可知初始化的servicebean全部作为事件接收对象,当ApplicationContext的publishEvent方法被触发时,每个实现了ApplicationListener接口的bean都会收到ApplicationEvent对象,每个ApplicationListener可根据事件类型只接收处理自己感兴趣的事件,通过查看service源码,

public void onApplicationEvent(ContextRefreshedEvent event) {

        if (isDelay() && !isExported() && !isUnexported()) {

            if (logger.isInfoEnabled()) {

          logger.info("The service ready on spring started. service: " + getInterface());

            }

            export();

        }

 }

可知每个servicebean对ContextRefreshedEvent感兴趣,当有ContextRefreshedEvent事件发生时,会进行export(),export操作就是dubbo开始暴露服务的入口。

 

关于ContextRefreshedEvent是何时触发的,由谁触发的来介绍下:在Spring中,ApplicationContext的子类AbstractApplicationContext的refresh()是构建Bean的入口点,spring在加载bean的时候,就会执行ConfigurableApplicationContext的refresh方法,看下refresh方法的实现:

 

 

finishRefresh的方法如下:



由上可知,当spring加载完一个bean的时候就会publishContextRefreshedEvent事件,而dubbo的servicebean监听了该事件,所以当该类型事件发生时,sevicebean会触发onApplicationEvent(ContextRefreshedEvent event),然后就会调用export方法了,dubbo时序图中的第一步找到了。

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326020655&siteId=291194637