您好,登錄后才能下訂單哦!
1,配置信息
先看看dubbo官方文檔給出的初始化過程:
基于 dubbo.jar 內(nèi)的 META-INF/spring.handlers 配置,Spring 在遇到 dubbo 名稱空間時(shí),會(huì)回調(diào) DubboNamespaceHandler。
所有 dubbo 的標(biāo)簽,都統(tǒng)一用 DubboBeanDefinitionParser 進(jìn)行解析,基于一對(duì)一屬性映射,將 XML 標(biāo)簽解析為 Bean 對(duì)象。
找到dubbo.jar中的spring.handlers及DubboBeanDefinitionParser:
spring.handlers:
http\://dubbo.apache.org/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler
DubboBeanDefinitionParser:
public class DubboNamespaceHandler extends NamespaceHandlerSupport {
static {
Version.checkDuplicate(DubboNamespaceHandler.class);
}
@Override
public void init() {
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", new AnnotationBeanDefinitionParser());
}
}
上述registerBeanDefinitionParser注冊(cè)對(duì)應(yīng)標(biāo)簽的解釋器,即當(dāng)遇到"application"(即<dubbo:application/>)時(shí),使用
new DubboBeanDefinitionParser(ApplicationConfig.class, true)對(duì)其進(jìn)行解析。
dubbo配置文件及其意義:
1、xmlns="http://www.springframework.org/schema/beans"
聲明xml文件默認(rèn)的命名空間,表示未使用其他命名空間的所有標(biāo)簽的默認(rèn)命名空間。
2、xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
聲明XML Schema 實(shí)例,聲明后就可以使用 schemaLocation 屬性
3、xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
聲明前綴為dubbo的命名空間,其惟一的作用是賦予命名空間一個(gè)惟一的名稱。當(dāng)命名空間被定義在元素的開始標(biāo)簽中時(shí),所有帶有相同前綴的子元素都會(huì)與同一個(gè)命名空間相關(guān)聯(lián)。即當(dāng)spring解析以dubbo開頭的標(biāo)簽時(shí),會(huì)把其命名空間設(shè)置為"http://code.alibabatech.com/schema/dubbo",而這個(gè)命名空間名稱和spring.handlers中的一個(gè)key是相同的,這即是它們產(chǎn)生聯(lián)系的地方。
4、xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
http://code.alibabatech.com/schema/dubbo http://code.alibabatech.com/schema/dubbo/dubbo.xsd"
這個(gè)從命名可以看出個(gè)大概,指定Schema的位置這個(gè)屬性必須結(jié)合命名空間使用。這個(gè)屬性有兩個(gè)值,第一個(gè)
值表示需要使用的命名空間。第二個(gè)值表示供命名空間使用的 XML schema 的位置。
2,源碼解析
配置文件解析發(fā)生在容器refresh的obtainFreshBeanFactory階段
調(diào)用棧:
進(jìn)到XmlBeanDefinitionReader#doLoadBeanDefinitions中:
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
//將配置文件解析為Document對(duì)象,其中級(jí)聯(lián)包含子節(jié)點(diǎn),每個(gè)子節(jié)點(diǎn)代表一個(gè)配置項(xiàng)
Document doc = doLoadDocument(inputSource, resource);
return registerBeanDefinitions(doc, resource);
}
..........
}
繼續(xù)往下走,來到DefaultBeanDefinitionDocumentReader#parseBeanDefinitions,這里開始遍歷解析子節(jié)點(diǎn):
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;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
由于是自定義的配置,將會(huì)進(jìn)入delegate.parseCustomElement(ele);
public BeanDefinition parseCustomElement(Element ele) {
return parseCustomElement(ele, null);
}
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
//獲取命名空間,如果是dubbo的配置,將會(huì)是"http://code.alibabatech.com/schema/dubbo"
String namespaceUri = getNamespaceURI(ele);
//更具命名空間,查找對(duì)應(yīng)的Handler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
進(jìn)到DefaultNamespaceHandlerResolver#resolve:
public NamespaceHandler resolve(String namespaceUri) {
//從jar包的META-INF/spring.handlers中讀取Handler信息
Map<String, Object> handlerMappings = getHandlerMappings();
Object handlerOrClassName = handlerMappings.get(namespaceUri);
if (handlerOrClassName == null) {
return null;
}
else if (handlerOrClassName instanceof NamespaceHandler) {
return (NamespaceHandler) handlerOrClassName;
}
else {
String className = (String) handlerOrClassName;
try {
Class<?> handlerClass = ClassUtils.forName(className, this.classLoader);
if (!NamespaceHandler.class.isAssignableFrom(handlerClass)) {
throw new FatalBeanException("Class [" + className + "] for namespace [" + namespaceUri +
"] does not implement the [" + NamespaceHandler.class.getName() + "] interface");
}
//實(shí)例化Handler
NamespaceHandler namespaceHandler = (NamespaceHandler) BeanUtils.instantiateClass(handlerClass);
//執(zhí)行初始化方法,指定不同的標(biāo)簽各自使用的解析器
namespaceHandler.init();
handlerMappings.put(namespaceUri, namespaceHandler);
return namespaceHandler;
}
.......
}
}
進(jìn)到getHandlerMappings方法:
private Map<String, Object> getHandlerMappings() {
if (this.handlerMappings == null) {
synchronized (this) {
if (this.handlerMappings == null) {
try {
Properties mappings =
PropertiesLoaderUtils.loadAllProperties(this.handlerMappingsLocation, this.classLoader);
if (logger.isDebugEnabled()) {
logger.debug("Loaded NamespaceHandler mappings: " + mappings);
}
Map<String, Object> handlerMappings = new ConcurrentHashMap<String, Object>(mappings.size());
CollectionUtils.mergePropertiesIntoMap(mappings, handlerMappings);
this.handlerMappings = handlerMappings;
}
}
}
}
return this.handlerMappings;
}
讀取文件的具體操作就不跟了,回到DefaultNamespaceHandlerResolver#resolve,看看獲取到的mapping:
其中一個(gè)則是以http://code.alibabatech.com/schema/dubbo 為鍵, DubboNamespaceHandler為值,因此,當(dāng)解析dubbo的元素時(shí),則會(huì)使用DubboNamespaceHandler
回到delegate.parseCustomElement,并進(jìn)入到handler.parse中:
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
return findParserForElement(element, parserContext).parse(element, parserContext);
}
findParserForElement(element, parserContext),查找對(duì)應(yīng)的解析器,即handler.init()中初始化的,然后對(duì)應(yīng)解析器開始解析Element,最終在DubboBeanDefinitionParser#parse中進(jìn)行構(gòu)建RootBeanDefinition,并將構(gòu)建好的RootBeanDefinition加入到容器中,并在容器refresh過程的finishBeanFactoryInitialization(beanFactory)中創(chuàng)建對(duì)應(yīng)實(shí)例。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。