Spring 源码之核心加载方法(2) 配置文件加载

2.1 loadBeanDefinitions

AbstractRefreshableApplicationContext#loadBeanDefinitions

定位: org.springframework.context.support.AbstractRefreshableApplicationContext#loadBeanDefinitions

加载配置文件(执行 xml, groovy 和注解方式)并生成 BeanDefinitions

AbstractXmlApplicationContext#loadBeanDefinitions

定位: org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 加载 xml 配置文件, 并注册 beanDefinition
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 创建一个 XmlBeanDefinitionReader, 并通过回调设置到 beanFactory 中
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

// Configure the bean definition reader with this context's
// resource loading environment.
// 给 beanDefinitionReader 对象设置对象
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
// 设置要用于解析的 SAX 实体解析器
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
// 初始化 beanDefinitionReader 对象,此处设置配置文件是否要进行验证
initBeanDefinitionReader(beanDefinitionReader);
// 加载并注册 beanDefinition
loadBeanDefinitions(beanDefinitionReader);
}

定位: org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(XmlBeanDefinitionReader)

1
2
3
4
5
6
7
8
9
10
11
12
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = getConfigResources();
if (configResources != null) {
// 从指定的资源加载 BeanDefinition
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// 从指定的资源位置加载 BeanDefinition
reader.loadBeanDefinitions(configLocations);
}
}

XmlBeanDefinitionReader#loadBeanDefinitions

定位org.springframework.beans.factory.xml.XmlBeanDefinitionReader#loadBeanDefinitions(EncodedResource)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
Assert.notNull(encodedResource, "EncodedResource must not be null");
if (logger.isTraceEnabled()) {
logger.trace("Loading XML bean definitions from " + encodedResource);
}

// 获取已经加载的资源记录
Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
if (currentResources == null) {
currentResources = new HashSet<>(4);
this.resourcesCurrentlyBeingLoaded.set(currentResources);
}
if (!currentResources.add(encodedResource)) {
throw new BeanDefinitionStoreException(
"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
}
// 从 encodedResource 中获取已经封装的 Resource 对象, 并再次从 Resource 中获取其中的 inputStream
try {
InputStream inputStream = encodedResource.getResource().getInputStream();
try {
InputSource inputSource = new InputSource(inputStream);
if (encodedResource.getEncoding() != null) {
inputSource.setEncoding(encodedResource.getEncoding());
}
// 实际从指定的XML文件加载 BeanDefinition (核心处理步骤)
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
}
finally {
inputStream.close();
}
}
catch (IOException ex) {
throw new BeanDefinitionStoreException(
"IOException parsing XML document from " + encodedResource.getResource(), ex);
}
finally {
currentResources.remove(encodedResource);
if (currentResources.isEmpty()) {
this.resourcesCurrentlyBeingLoaded.remove();
}
}
}

XmlBeanDefinitionReader#doLoadBeanDefinitions

定位: org.springframework.beans.factory.xml.XmlBeanDefinitionReader#doLoadBeanDefinitions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
/*
* 此解析过程是由 XmlBeanDefinitionReader 来完成,
* 从 重载 loadBeanDefinitions方法 (String[] -> string -> Resource[] -> resource) ,
* 最终开始将 resource 读取成一个 document 文档,根据文档的节点信息封装成一个个的 BeanDefinition 对象
*/
try {
// 将inpustream转换成Document, 此处获取 xml 文件的 document 对象,
Document doc = doLoadDocument(inputSource, resource);
// 注册 xml 文件定义的 BeanDefinition
int count = registerBeanDefinitions(doc, resource);
// ... 省略日志打印
return count;
}
catch (...) {
// ... 省略
}
}
XmlBeanDefinitionReader#registerBeanDefinitions

定位: org.springframework.beans.factory.xml.XmlBeanDefinitionReader#registerBeanDefinitions

1
2
3
4
5
6
7
8
9
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
// 委托模式,BeanDefinitionDocumentReader 委托这个类进行 document 的解析
// 创建 BeanDefinitionDocumentReader, 以用于实际从XML文档读取bean定义
BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
int countBefore = getRegistry().getBeanDefinitionCount();
// 从给定的DOM文档中读取bean定义,并将他们向注册到注册表中
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
return getRegistry().getBeanDefinitionCount() - countBefore;
}
XmlBeanDefinitionReader#doRegisterBeanDefinitions

定位: org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 创建BeanDefinitionParserDelegate委托对象,交给parseBeanDefinitions处理
protected void doRegisterBeanDefinitions(Element root) {
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;
}
}
}
// 解析 xml 的前置逻辑(扩展点, 钩子方法)
preProcessXml(root);
// 真正的解析方法, 处理默认命名空间的标签("import"、"alias"、"bean") 和 自定义的标签
parseBeanDefinitions(root, this.delegate);
// 解析 xml 的后置处理逻辑(扩展点, 钩子方法)
postProcessXml(root);

this.delegate = parent;
}
DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

定位: org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader#parseBeanDefinitions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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)) {
// 文件的命名空间为 http://www.springframework.org/schema/beans
// 解析 "import", "alias", "bean", "beans" 标签
parseDefaultElement(ele, delegate);
}
else {
// 处理自定义的标签
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}