Spring源码解析(一) 创建Bean工厂
SunRan

前言

1
2
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
User userEntity = (User) context.getBean("userEntity");

通过 application.xml 定义一些Bean对象,在项目启动后会由Spring的Bean工厂进行管理。

这一切都要从 refresh 说起。

1
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

obtainFreshBeanFactory() 主要做了两件事:

  1. 创建了一个容器对象——DefaultListableBeanFactory

  2. 解析自定义的Bean对象(XML、注解等),设置到 beanDefinition

抽象流程

image-20220120161922862

XML的解析过程: String -> Resource[] -> EncodedResource ->Document->BeanDefinition

创建容器对象

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
/**
* This implementation performs an actual refresh of this context's underlying
* bean factory, shutting down the previous bean factory (if any) and
* initializing a fresh bean factory for the next phase of the context's lifecycle.
*/
@Override
protected final void refreshBeanFactory() throws BeansException {
// 如果存在beanFactory,则销毁beanFactory
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建DefaultListableBeanFactory对象
DefaultListableBeanFactory beanFactory = createBeanFactory();
// 为了序列化指定id,可以从id反序列化到beanFactory对象
beanFactory.setSerializationId(getId());
// 定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
customizeBeanFactory(beanFactory);
// 初始化documentReader,并进行XML文件读取及解析,默认命名空间的解析,自定义标签的解析
loadBeanDefinitions(beanFactory);
// 将创建的Bean工厂设置到对象属性中
this.beanFactory = beanFactory;
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

refreshBeanFactory首先会创建一个BeanFactory对象,并做一些基础的配置,最后加载BeanDefinition

1
2
3
protected DefaultListableBeanFactory createBeanFactory() {
return new DefaultListableBeanFactory(getInternalParentBeanFactory());
}

DefaultListableBeanFactory就是最终的BeanFactory对象。

解析自定义Bean对象

refreshBeanFactory()中有一个loadBeanDefinitions(),初始化documentReader对XML文件进行读取,最终得到BeanDefinitions

BeanDefinitions是什么?

虽然通过Reader对象读取解析得到了BeanDefinitions,但是它并不是真正意义上的Bean对象。

可以理解为是一个 XML 到 Bean 的一个中间状态,无论你的Bean通过什么方式定义只要你能解析为BeanDefinitions我都可以把他创建成一个Spring Bean。

loadBeanDefinitions

1
2
3
4
5
6
7
8
9
10
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
// 创建一个xml的beanDefinitionReader,并通过回调设置到beanFactory中
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

// 一些配置操作,省略

// 开始完成beanDefinition的加载
loadBeanDefinitions(beanDefinitionReader);
}

loadBeanDefinitions方法中创建了XmlBeanDefinitionReader后续会通过Reader对象对XML进行一个读取和解析。

并且loadBeanDefinitions运用了重载,虽然还是那个名字但是参数发生了改变。参数从Bean工厂变成了Reader

1
2
3
4
5
6
7
8
9
10
11
12
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
// 以Resource的方式获得配置文件的资源位置
Resource[] configResources = getConfigResources();
if (configResources != null) {
reader.loadBeanDefinitions(configResources);
}
// 以String的形式获得配置文件的位置
String[] configLocations = getConfigLocations();
if (configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}

此处就要看你在new ClassPathXmlApplicationContext()的时候参数传的是什么了,分别执行两个方法。

loadBeanDefinitions

需要注意的是,执行的方法虽然还是loadBeanDefinitions 但是已经执行的不是原来那个对象的方法了,此时到了AbstractBeanDefinitionReader对象。

1
2
3
4
5
6
7
8
9
@Override
public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
Assert.notNull(locations, "Location array must not be null");
int count = 0;
for (String location : locations) {
count += loadBeanDefinitions(location);
}
return count;
}

因为参数是一个字符串的数组,此处对数组进行遍历,对字符串的资源地址再次执行loadBeanDefinitions方法。

返回结果是一个int,也就是对应的资源地址加载成功的Bean数量。

loadBeanDefinitions

随后经历数次loadBeanDefinitions方法,直接跳过了…

doLoadBeanDefinitions

Spring源码中很多名字叫 doXXXX 的对象才是真正干活的对象。

1
2
3
4
5
6
7
8
9
10
11
try {
// 此处获取xml文件的document对象,这个解析过程是由documentLoader完成的,
// 从String[] -string-Resource[]- resource,最终开始将resource读取成一个document文档
// 根据文档的节点信息封装成一个个的BeanDefinition对象
Document doc = doLoadDocument(inputSource, resource);
int count = registerBeanDefinitions(doc, resource);
if (logger.isDebugEnabled()) {
logger.debug("Loaded " + count + " bean definitions from " + resource);
}
return count;
}

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

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);
// 解析BeanDefinitions
parseBeanDefinitions(root, this.delegate);
postProcessXml(root);

this.delegate = parent;
}

parseBeanDefinitions

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
}
}

对整个XML文件进行逐行变量

parseDefaultElement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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></bean>自然会执行processBeanDefinition

processBeanDefinition

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
/**
* Process the given bean element, parsing the bean definition
* and registering it with the registry.
*/
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// beanDefinitionHolder是beanDefinition对象的封装类,封装了BeanDefinition,bean的名字和别名,用它来完成向IOC容器的注册
// 得到这个对象就意味着beandefinition是通过BeanDefinitionParserDelegate
// 对xml元素的信息按照spring的bean规则进行解析得到的
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 向ioc容器注册解析得到的beandefinition的地方
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
// 在beandefinition向ioc容器注册完成之后,发送消息
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

registerBeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 获取BeanName
String beanName = definitionHolder.getBeanName();
// 使用beanName做唯一标识注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

// Register aliases for bean name, if any.
// 注册所有的别名
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}

registerBeanDefinition

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

// 省略 ....

else {
// Still in startup registration phase
// 注册beanDefinition
this.beanDefinitionMap.put(beanName, beanDefinition);
// 记录beanName
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;


// 省略 ....
}

此时registerBeanDefinition已经回到了DefaultListableBeanFactory方法,正常执行来说主要会做如下操作:

  • 将解析成功的Bean对象名称加到beanDefinitionNames的列表中
  • 将BeanName和BeanDefinition的键值对存放在beanDefinitionMap

至此,就将五花八门的自定义Bean解析为了BeanDefinition,并存放在了BeanFactory中,后续需要加载某个Bean时只需要根据名称到map中找到对应的BeanDefinition即可,然后执行doCreateBean方法。

  • 本文标题:Spring源码解析(一) 创建Bean工厂
  • 本文作者:SunRan
  • 创建时间:2022-01-20 14:48:17
  • 本文链接:https://lksun.cn/2022/01/20/Spring源码解析-一-创建Bean工厂/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论