导航
导航
文章目录
  1. 一、前言
  2. 二、分析
    1. 2.1 registerBeanDefinition
    2. 2.2 registerAlias
  3. 三、小结

[断点分析之spring-ioc]-BeanDefinitionHolder注册(七)

一、前言

​ 通过前面大批量的工作,终于要到注册BeanDefinitionHolder这一步了.当然还是通过一下代码作为入口进行分析.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
// 解析xml元素
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 装饰bean
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
// 注册bean到容器中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
// 发送事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}

​ 解析、装饰都已经记录了,解析来的重点就是BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());这句代码了.

二、分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// 注册 bean
// Register bean definition under primary name.
// 获取 bean 的名称
String beanName = definitionHolder.getBeanName();
// 注册
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

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

BeanDefinitionRegistry这个对象是通过XmlReaderContext中获取的.

1
2
3
4
// XmlReaderContext
public final BeanDefinitionRegistry getRegistry() {
return this.reader.getRegistry();
}

​ 而这个reader则是XmlBeanDefinitionReader,registry对象则通过XmlBeanDefinitionReader的构造方法传入进来,实际上这个registry对象就是XmlBeanFactory或者说是DefaultListableBeanFactory,因为这两个有继承关系.

images

2.1 registerBeanDefinition

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// DefaultListableBeanFactory
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {

Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");

if (beanDefinition instanceof AbstractBeanDefinition) {
try {
// 校验 bean 的定义是否合法
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
// 从缓存中取出 BeanDefinition
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
// bean 已被注册过
if (existingDefinition != null) {
// 如果不允许重复注册则抛出异常
if (!isAllowBeanDefinitionOverriding()) {
throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
}
else if (existingDefinition.getRole() < beanDefinition.getRole()) {
// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
if (logger.isInfoEnabled()) {
logger.info("Overriding user-defined bean definition for bean '" + beanName +
"' with a framework-generated bean definition: replacing [" +
existingDefinition + "] with [" + beanDefinition + "]");
}
}
else if (!beanDefinition.equals(existingDefinition)) {
if (logger.isDebugEnabled()) {
logger.debug("Overriding bean definition for bean '" + beanName +
"' with a different definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
else {
if (logger.isTraceEnabled()) {
logger.trace("Overriding bean definition for bean '" + beanName +
"' with an equivalent definition: replacing [" + existingDefinition +
"] with [" + beanDefinition + "]");
}
}
// 放入到 map 中
// 覆盖
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
// 判断是否有创建中的bean
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
// 加锁
// 不能修改启动时的集合,需要重新创建一个集合
synchronized (this.beanDefinitionMap) {
// 放入map中
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
// 如果这个已经 bean 在存在 则移除
removeManualSingletonName(beanName);
}
}
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
// 如果这个已经 bean 在存在 则移除
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
//注册成功,如果是重复注册的则销毁之前注册的bean
if (existingDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}

​ 这个阶段呢,bean都还没开始创建,都是在做解析,注册之类的事情,所以这里有一个判断看起来比较迷惑hasBeanCreationStarted.或许后面才会知道这个判断条件有啥用吧.

  1. 验证beanDefinition是否合法

    1. 判断bean是否被注册过,如果不允许重复注册则抛出异常
    2. 如果允许重复注册则放入beanDefinitionMap这个map集合中
    3. 如果该beanDefinition未被注册过,则添加映射到beanDefinitionMap中去和beanDefinitionNames集合中去.
    4. 注册成功,如果是重复注册的则销毁之前注册的bean

2.2 registerAlias

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
43
44
// SimpleAliasRegistry
@Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
// 加锁 并发控制
synchronized (this.aliasMap) {
// 判断 bean 名称是否与别名相同,如果相同则忽略
if (alias.equals(name)) {
// 移除别名
this.aliasMap.remove(alias);
if (logger.isDebugEnabled()) {
logger.debug("Alias definition '" + alias + "' ignored since it points to same name");
}
}
else {
// 判断别名是否已存在
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
// 如果别名对应的bean的名称与name相同则忽略
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
return;
}
// 是否允许覆盖,如果不允许则报错
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot define alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
if (logger.isDebugEnabled()) {
logger.debug("Overriding alias '" + alias + "' definition for registered name '" +
registeredName + "' with new target name '" + name + "'");
}
}
//检查是否有循环引用别名 例如:A-B C-B A-C
checkForAliasCircle(name, alias);
//映射别名和名称到map中
this.aliasMap.put(alias, name);
if (logger.isTraceEnabled()) {
logger.trace("Alias definition '" + alias + "' registered for name '" + name + "'");
}
}
}
}
  1. 判断别名是否与bean名称是否相同
  2. 如果相同则移除别名
  3. 判断别名是否已经存在
  4. 如果不存在检查是否存在循环引用
  5. 映射别名

​ 这里检测是否存在循环引用比较有意思,之前文章应该记录到了这块儿的逻辑.

三、小结

​ bean的解析与注册已经分析完了,接下来就是重头戏了,终于要看看 spring 是怎么根据BeanDefinition来创建bean对象.

支持一下
扫一扫,请我吃颗大白兔奶糖
  • 支付宝扫一扫