Dubbo 源码学习笔记(一)Spring容器解析dubbo配置流程
基于dubbo-2.6.0.jar 内的 META-INF/spring.hanlers 配置,Spring 在遇到dubbo命名空间的时,会回调DubboNamespaceHandler。
所有dubbo的标签,都统一用DubboBeanDefinitionParser 进行解析,基于一对一属性的映射,将XML标签解析为Bean对象。
一、启动Spring 容器
// SpringContainer
public void start() {
String configPath = ConfigUtils.getProperty(SPRING_CONFIG);
if (configPath == null || configPath.length() == 0) {
configPath = DEFAULT_SPRING_CONFIG;
}
context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"));
context.start();
}
二、Spring refresh()->obtainFreshBeanFactory() 获取beanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
this.refreshBeanFactory(); //创建DefaultListableBeanFactory
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
三、创建一个DefaultListableBeanFactory
protected final void refreshBeanFactory() throws BeansException {
if (this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
// 创建DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory); //从指定的XML文件加载bean定义
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
四、loadBeanDefinitions从指定的XML文件加载bean定义
//loadBeanDefinitions:93, AbstractXmlApplicationContext
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
}
五、解析xml信息
//registerBeanDefinitions:94, DefaultBeanDefinitionDocumentReader
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
Element root = doc.getDocumentElement();
doRegisterBeanDefinitions(root);
}
//1 . 执行doRegisterBeanDefinitions:142, DefaultBeanDefinitionDocumentReader
//2 . doRegisterBeanDefinitions:142, DefaultBeanDefinitionDocumentReader
//3 . parseBeanDefinitions:172, DefaultBeanDefinitionDocumentReader
//parseCustomElement:1406, BeanDefinitionParserDelegate
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele); //=http://code.alibabatech.com/schema/dubbo
// 从handlerMappings 中获取到DubboNamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//调用 DubboNamespaceHandler的.parse()方法
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
5.1、获取xml命名空间的解析器DubboNamespaceHandler
读取所有jar包下的META-INF/spring.handlers 文件,从中加载映射关系,通过namespaceUri得到DubboNamespaceHandler
// resolve:131, DefaultNamespaceHandlerResolver
public NamespaceHandler