About the introduction of Dubbo and use, and the design of the framework, website dubbo.apache.org/zh/docs/v2…. (version 2.7) are introduced. I believe that as long as you are patient, you can basically have an overall understanding of Dubbo. It is important to note that you need to have at least a basic understanding of Dubbo so that you don’t get confused about the source code.
The official documentation for Dubbo is pretty good. In addition to the user manual, there is an introduction to the principles and even an analysis of the source code. But I think there are still shortcomings, that is, the analysis of the official website soon into the details, after reading the brain is still buzzing, I think the lack of a grasp of the overall, as well as between modules or interfaces between interfaces.
Next, we understand the integration of Spring and Dubbo. Just as the last few articles have analyzed the principle of Spring IoC, so follow the lead and analyze the application of Spring IoC extension, which is the integration of Dubbo.
As of this writing, Dubbo has been updated to 3.0.1, and my analysis is based on the 2.6.x branch.
Dubbo module partition, do still quite good of, reference dubbo.apache.org/zh/docs/v2…. , seen from the module, and Spring integration module is dubbo – config – Spring, there are two key categories, one is com. Alibaba. Dubbo. Config. Spring. ServiceBean, One is com. Alibaba. Dubbo. Config. Spring. ReferenceBean, as can be seen from the name, ServiceBean is related to service export and registration, ReferenceBean is associated with a service reference, basically see ServiceBean here.
ServiceBean class
Take a look at the inheritance architecture of ServiceBean
Interesting ~, the graph generating ServiceBean ApplicationContextAware, so can inject ApplicationContext, realize ApplicationEventPublisherAware, so you can publish event, It is also an ApplicationListener, so it can receive events, and DisposableBean and InitializingBean, so that you can perform some extended functions when the Bean is initialized and destroyed.
The first is the afterPropertiesSet() method
public void afterPropertiesSet(a) throws Exception {
/ /... Omit, related to loading configuration, but not this time
if (!isDelay()) {
export();
}
}
Copy the code
If the service is not delayed exposed, it will be exposed in afterPropertiesSet, but when I run the single test locally, delay is empty, so isDelay() returns true. There is no service exposed here, so look at onApplicationEvent(), which is triggered when the container event is refreshed
public void onApplicationEvent(ContextRefreshedEvent event) {
if(isDelay() && ! isExported() && ! isUnexported()) {if (logger.isInfoEnabled()) {
logger.info("The service ready on spring started. service: "+ getInterface()); } export(); }}Copy the code
This method is simpler and calls export() to the same method as above, so extension integration is also easier
There is also the question of how, for example, Dubbo’s beans are managed by the Spring IoC container
DubboNamespaceHandler class
So here’s an example,
Add the Spring. handlers file to the meta-INF directory in the classpath
http\://bubbo.apache.org/schema/bubbo=spring.schema.BubboNamespaceHandler
Copy the code
In addition, add the spring.schemas file, whose content is
http\://bubbo.apache.org/schema/bubbo/bubbo.xsd=META-INF/bubbo.xsd
Copy the code
Finally, add bubbo. XSD. If you don’t know XML schema, you can go to see it first
<? xml version="1.0" encoding="UTF-8" standalone="no"? > <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
xmlns="http://bubbo.apache.org/schema/bubbo"
targetNamespace="http://bubbo.apache.org/schema/bubbo">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:element name="bubbo">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="beans:identifiedType">
<xsd:attribute name="protocol" type="xsd:string" />
<xsd:attribute name="version" type="xsd:string" />
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Copy the code
<bubbo:protocol=”bubbo” version=”1.0.0″/>
The key is to parse these schemas, such as the BubboNamespaceHandler
public class BubboNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init(a) {
System.out.println("BubboNamespaceHandler..."); }}Copy the code
And DubboNamespaceHandler configuration parsing, all by DubboBeanDefinitionParser, this class implements the BeanDefinitionParser
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
@Override
public void init(a) {
registerBeanDefinitionParser("application".new DubboBeanDefinitionParser(ApplicationConfig.class, true));
registerBeanDefinitionParser("module".new DubboBeanDefinitionParser(ModuleConfig.class, true));
registerBeanDefinitionParser("registry".new DubboBeanDefinitionParser(RegistryConfig.class, true));
registerBeanDefinitionParser("monitor".new DubboBeanDefinitionParser(MonitorConfig.class, true));
registerBeanDefinitionParser("provider".new DubboBeanDefinitionParser(ProviderConfig.class, true));
registerBeanDefinitionParser("consumer".new DubboBeanDefinitionParser(ConsumerConfig.class, true));
registerBeanDefinitionParser("protocol".new DubboBeanDefinitionParser(ProtocolConfig.class, true));
registerBeanDefinitionParser("service".new DubboBeanDefinitionParser(ServiceBean.class, true));
registerBeanDefinitionParser("reference".new DubboBeanDefinitionParser(ReferenceBean.class, false));
registerBeanDefinitionParser("annotation".newAnnotationBeanDefinitionParser()); }}Copy the code
Maybe we want to ask again, when does this parse get triggered
The key is
DefaultBeanDefinitionDocumentReader
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
// This determines whether to load Spring's namespace or a custom namespace
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else{ delegate.parseCustomElement(ele); }}}}else{ delegate.parseCustomElement(root); }}Copy the code
So, the idea of integration is simple