Spring-IOC之解析和装饰自定义元数据

解析条件和流程

  当容器通过DefaultBeanDefinitionDocumentReader的doRegisterBeanDefinitions方法解析元数据时,不仅可以解析4种内置的元数据(import、alias、bean、beans),还可以解析自定义元数据。

protected void doRegisterBeanDefinitions(Element root) {
   
	BeanDefinitionParserDelegate parent = this.delegate;
	this.delegate = createDelegate(getReaderContext(), root, parent);
	if (this.delegate.isDefaultNamespace(root)) {
   
		// 解析内置的<beans>根元素
		……
	}
	// 前置处理
	preProcessXml(root);
	// 解析<beans>下各子元素
	parseBeanDefinitions(root, this.delegate);
	// 后置处理
	postProcessXml(root);
	
	this.delegate = parent;
}

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);
	}
}

  如上代码所示,元素的命名空间决定了解析流程:

  1. 命名空间为容器默认值,则调用parseDefaultElement方法按默认解析流程处理即可,具体处理细节请参考《Spring-IOC之BeanFactory启动流程》;
  2. 命名空间为自定义值,则DefaultBeanDefinitionDocumentReader认为当前遍历到的是一个自定义元素,此时将委派BeanDefinitionParserDelegate通过parseCustomElement方法来解析。
public class BeanDefinitionParserDelegate {
   

	private final XmlReaderContext readerContext;

	public BeanDefinitionParserDelegate(XmlReaderContext readerContext) {
   
		Assert.notNull(readerContext, "XmlReaderContext must not be null");
		this.readerContext = readerContext;
	}

	public BeanDefinition parseCustomElement(Element ele) {
   
		return parseCustomElement(ele, null);
	}

	public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
   
		// 获取自定义元素的命名空间
		String namespaceUri = getNamespaceURI(ele);
		// NamespaceHandlerResolver将命名空间解析成对应的NamespaceHandler
		NamespaceHandler handler = this.readerContext
			.getNamespaceHandlerResolver().resolve(namespaceUri);
		……
		// NamespaceHandler将元数据解析成BeanDefinition
		return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
	}
}

  如上代码所示,解析自定义元素时需要两个重要的组件来参与,即命名空间处理解析器 (NamespaceHandlerResolver)和命名空间处理器(NamespaceHandler),其流程如下:

  1. BeanDefinitionParserDelegate获取当前自定义元素的命名空间;
  2. 利用NamespaceHandlerResolver将命名空间解析(resolve)成相应的NamespaceHandler;
  3. 利用NamespaceHandler最终将自定义元数据解析(parse)成BeanDefinition后返回结果。

命名空间处理解析器(NamespaceHandlerResolver)

  在parseCustomElement方法中可看出,NamespaceHandlerResolver需要从XmlReaderContext(XML上下文读取器)中获取,而XmlReaderContext绑定的NamespaceHandlerResolver实例默认为DefaultNamespaceHandlerResolver,这是容器在启动期间由XmlBeanDefinitionReader通过registerBeanDefinitions方法开始解析时所创建,如下代码所示。

public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader {
   
	
	public int registerBeanDefinitions(Document doc, Resource resource) 
		throws BeanDefinitionStoreException {
   

		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		int countBefore = getRegistry().getBeanDefinitionCount();
		// 开始解析时创建XmlReaderContext
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

	public XmlReaderContext createReaderContext(Resource resource) {
   
		// 创建XmlReaderContext实例时绑定NamespaceHandlerResolver 
		return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值