您当前的位置: 首页 >  spring

墨家巨子@俏如来

暂无认证

  • 1浏览

    0关注

    188博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Spring源码剖析-IOC启动流程(三)

墨家巨子@俏如来 发布时间:2021-06-02 20:00:59 ,浏览量:1

前言

这篇文章是接上一篇文章《IOC启动流程(二)》,上一章节我们见到了Spring IOC容器的容器创建和配置加载两个大的流程,接来下分析Bean的解析以及Bean的注册流程。这里我终于可以把IOC启动流程的大图放上来了,你可以根据该图来看我接下来的流程分析 在这里插入图片描述

Bean的解析:XmlBeanDefinitionReader

Spring IOC启动创建完容器之后,最终委托XmlBeanDefinitionReader#loadBeanDefinitions加载Bean。

XmlBeanDefinitionReader通过 ResourcePatternResolver 加载配置XML转换为 Resource对象并封装成InputSource 文档解析源,然后XmlBeanDefinitionReader通过DocumentLoader.loadDocument 把InputSource(XML配置文件)解析成Document。最后调用registerBeanDefinitions方法解析和注册Bean :见XmlBeanDefinitionReader#loadBeanDefinitions源码如下:

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			//将 XML 文件转换为 Document 对象,通过 documentLoader来解析
			Document doc = doLoadDocument(inputSource, resource);
			//【重要】解析和注册Bean的消息流程
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			return count;
		}
		...省略...

下面是:DefaultDocumentLoader#loadDocument 加载文档源码:

//XML解析成Document,调用documentLoader.loadDocument完成
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
		return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
				getValidationModeForResource(resource), isNamespaceAware());
}
	
public Document loadDocument(InputSource inputSource, EntityResolver entityResolver,
			ErrorHandler errorHandler, int validationMode, boolean namespaceAware) throws Exception {
		//创建文档解析工厂
		DocumentBuilderFactory factory = createDocumentBuilderFactory(validationMode, namespaceAware);
		if (logger.isTraceEnabled()) {
			logger.trace("Using JAXP provider [" + factory.getClass().getName() + "]");
		}
		//创建文档解析器
		DocumentBuilder builder = createDocumentBuilder(factory, entityResolver, errorHandler);
		//执行解析了
		return builder.parse(inputSource);
	}

下面是registerBeanDefinitions方法,即:Bean的解析和注册流程:

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//Bean的文档解析器,由 DefaultBeanDefinitionDocumentReader 实现
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//容器中Bean的数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//通过 DefaultBeanDefinitionDocumentReader .registerBeanDefinitions 注册Bean
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//统计解析的Bean的个数
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

这里创建了DefaultBeanDefinitionDocumentReaderBean的文档解析器,调用其registerBeanDefinitions方法来注册Bean,见:DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

DefaultBeanDefinitionDocumentReader#registerBeanDefinitions

DefaultBeanDefinitionDocumentReader委派BeanDefinitionParserDelegate进行Document的解析工作

@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
	this.readerContext = readerContext;
	//获取根元素,调用doRegisterBeanDefinitions方法
	doRegisterBeanDefinitions(doc.getDocumentElement());
}

protected void doRegisterBeanDefinitions(Element root) {
		//创建BeanDefinitionParserDelegate,它是Bean解析委派器,定义了XML的各种元素的解析
		BeanDefinitionParserDelegate parent = this.delegate;
		this.delegate = createDelegate(getReaderContext(), root, parent);

		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}
		//解析之前的动作,空方法,可以通过复写该方法做扩展
		preProcessXml(root);
		//解析Document,从root开始,委派给BeanDefinitionParserDelegate来解析
		parseBeanDefinitions(root, this.delegate);
		//解析之后的动作,空方法,可以通过复写该方法做扩展
		postProcessXml(root);

		this.delegate = parent;
	}

该方法中创建了BeanDefinitionParserDelegate,它定义了Spirng的xml中的所有的元素,然后委派它来对Document进行解析,继续跟 BeanDefinitionParserDelegate.parseBeanDefinitions 方法

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//判断是否使用默认的Spring的xml默认的命名空间
		if (delegate.isDefaultNamespace(root)) {
			//获取根元素下的所有元素
			NodeList nl = root.getChildNodes();
			for (int i = 0; i             
关注
打赏
1651329177
查看更多评论
0.0504s