标签解析
前面对Spring解析对象的整体做些整理,下面进出核心方法registerBeanDefinitions
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
......
}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
//实例化BeanDefinitionDocumentReader
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
//记录统计前BeanDefinition加载个数
int countBefore = getRegistry().getBeanDefinitionCount();
//加载及注册Bean
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
//记录本次加载的BeanDefinition个数
return getRegistry().getBeanDefinitionCount() - countBefore;
}
registerBeanDefinitions 里执行了doRegisterBeanDefinitions() -> parseBeanDefinitions() 看下时序图
image.png
parseBeanDefinitions方法针对默认标签和自定义标签处理。
默认标签处理
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
先看下Bean标签的处理:processBeanDefinition
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
其实上Spring源码很方便理解,每个功能方法都是下面的总纲。
processBeanDefinition方法的大致逻辑
1、BeanDefinitionParserDelegate进行元素解析,返回BeanDefinitionParserDelegate实例bdHolder,实例里已经有了id,class,alias等属性 。
具体解析逻辑:BeanDefinitionParserDelegate.parseBeanDefinitionElement() -> parseBeanDefinitionElement() 针对不同标签处理
2、如果实例不为空,若默认标签下子标签存在自定义标签,使用自定义标签处理
3、对解析后的bdHolder注册(维护 beanName:beanDefinition的map)
DefaultListableBeanFactory.registerBeanDefinition()
4、最后发出响应事件,bean加载完成
自定义标签处理
public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
//获取对应的命名空间
String namespaceUri = getNamespaceURI(ele);
if (namespaceUri == null) {
return null;
}
//根据命名空间找到对应NamespaceHandler
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
//调用自定义的NamespaceHandler进行解析
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
至此,Bean解析和注册的代码和结构大体有了了解。
我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=200l148seo740
网友评论