spring源码分析之——spring bean配置文件解析

上面一篇提到了bean加载的入口:

AbstractRefreshableApplicationContext的refreshBeanFacotry中有一行代码:

loadBeanDefinitions(beanFactory);

 当前的applicationcontext的实现类是xmlwebapplicationContext,所以最终的loadbeanDefinitions(beanFactory)

 方法的实现是在xmlwebapplicationContext中:

 

  protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
        // Create a new XmlBeanDefinitionReader for the given BeanFactory.
        XmlBeanDefinitionReader beanDefinitionReader = XBeanHelper.createBeanDefinitionReader(this, beanFactory, xmlPreprocessors);

        // Configure the bean definition reader with this context's
        // resource loading environment.
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

        // Allow a subclass to provide custom initialization of the reader,
        // then proceed with actually loading the bean definitions.
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

   很容易就能发现,bean的加载的是通过最后一行实现的。继续追踪进入源码:

 

protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
		String[] configLocations = getConfigLocations();
		if (configLocations != null) {
			for (String configLocation : configLocations) {
				reader.loadBeanDefinitions(configLocation);
			}
		}
	}

 现在知道为什么可以在web.xml中配置spring的时候指定多个配置文件了吧?哈哈。

 继续追踪XmlBeanDefinitionReader这个类。这个类继承了AbstractBeanDefinitionReader。AbstractBeanDefinitionReader还有一个实现类:PropertiesBeanDefinitionReader。

从名字很容易可以看出spring能支持基于xml和基于properties文件的bean加载方式。XmlBeanDefinitionReader

过把xml加载到一个Document对象里面,然后通过BeanDefinitionDocumentReader来分析这个document对象。

BeanDefinitionDocumentReader的默认实现类是:DefaultBeanDefinitionDocumentReader。

其中注册bean的代码如下:

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;

		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();

		BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);

		preProcessXml(root);
		parseBeanDefinitions(root, delegate);
		postProcessXml(root);
	}

 spring在这里提供了xml配置文件解析的两个扩展接口:preProcessXml,postProcessXml. 用户可以根据自身需求

 扩展这两个接口。下面就关注一下上面代码里面加载bean的核心方法:parseBeanDefinition.

 

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(delegate.getNamespaceURI(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;
					String namespaceUri = delegate.getNamespaceURI(ele);
					if (delegate.isDefaultNamespace(namespaceUri)) {
						parseDefaultElement(ele, delegate);
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);
		}
	}

 

  从上面代码可以看出,xml配置文件里面的<beans></beans>标签里面的闭合标签被解析成一个个Node.然后

  调用每个标签的NameSpaceHandler进行标签的解析,并注册相应的bean。比如:解析<aop:config></aop:config>

 这种标签时会调用AopNamespaceHandler来进行解析。对于使用默认NameSpace的标签,又分为import,alias,bean三个标签进行解析并注册相应的bean。

 

至此,bean的注入的轮廓基本清晰了。有兴趣的朋友可以沿着这个思路继续深入一些细节,比如aop的注入等等。

 

 

    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/softtech2008/article/details/83765144
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞