十八、parentBeanFactory和依赖处理

parentBeanFactory和依赖处理

如果从单例缓存中没有获取到单例 Bean 对象,则说明两种两种情况:

  1. 该 Bean 的 scope 不是 singleton
  2. 该 Bean 的 scope 是 singleton ,但是没有初始化完成。
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
// AbstractBeanFactory.java
//protected <T> T doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

// ... 省略很多代码

// <3> 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// <4> 如果容器中没有找到,则从父类容器中加载
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
String nameToLookup = originalBeanName(name);
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

// <5> 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}

try {
// <6> 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查给定的合并的 BeanDefinition
checkMergedBeanDefinition(mbd, beanName, args);

// Guarantee initialization of beans that the current bean depends on.
// <7> 处理所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// 若给定的依赖 bean 已经注册为依赖给定的 bean
// 循环依赖的情况
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// 缓存依赖调用
registerDependentBean(dep, beanName);
try {
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
}

// ... 省略很多代码

该段主要处理了:

1、检测,若当前 Bean 在创建,则抛出 BeanCurrentlyInCreationException 异常。

2、如果 beanDefinitionMap 中不存在 beanName 的 BeanDefinition(即在 Spring bean 初始化过程中没有加载),则尝试从 parentBeanFactory 中加载。

3、判断是否为类型检查。

4、从 mergedBeanDefinitions 中获取 beanName 对应的 RootBeanDefinition 对象。如果这个 BeanDefinition 是子 Bean 的话,则会合并父类的相关属性。

5、依赖处理。

检测

Spring 只解决单例模式下的循环依赖,对于原型模式的循环依赖则是抛出 BeanCurrentlyInCreationException 异常,所以首先检查该 beanName 是否处于原型模式下的循环依赖。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// AbstractBeanFactory.java
//正在创建的原型Bean
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");

if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}

检查父类BeanFactory

containsBeanDefinition(String beanName) 方法中不存在 beanName 相对应的 BeanDefinition 对象时,则从 parentBeanFactory 中获取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// AbstractBeanFactory.java

// 获取 parentBeanFactory
BeanFactory parentBeanFactory = getParentBeanFactory();
// parentBeanFactory 不为空且 beanDefinitionMap 中不存该 name 的 BeanDefinition
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 确定原始 beanName
String nameToLookup = originalBeanName(name);
// 若为 AbstractBeanFactory 类型,委托父类处理
if (parentBeanFactory instanceof AbstractBeanFactory) {
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 委托给构造���数 getBean() 处理
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else {
// 没有 args,委托给标准的 getBean() 处理
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
}

在获取实例Bean之前,先通过originalBeanName()方法对name进行了处理用来获取原始BeanName。

1
2
3
4
5
6
7
8
// AbstractBeanFactory.java
protected String originalBeanName(String name) {
String beanName = transformedBeanName(name);
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}

优先调用了transformedBeanName()方法(doGetBean()方法第一步就是调用了该方法),然后再对返回的beanname进行处理,因为上一步将&去掉了。

类型检查

方法参数 typeCheckOnly ,是用来判断调用 getBean(...) 方法时,表示是否为仅仅进行类型检查获取 Bean 对象。如果不是仅仅做类型检查,而是创建 Bean 对象,则需要调用 markBeanAsCreated(String beanName) 方法,进行记录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//AbstractBeanFactory.java
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
throws BeansException {
/********省略**********/
//标记当前bean正在创建中,alreadyCreated中
if (!typeCheckOnly) {
markBeanAsCreated(beanName);
}
/********省略**********/
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
protected void markBeanAsCreated(String beanName) {
// 没有创建
if (!this.alreadyCreated.contains(beanName)) {
// 加上全局锁
synchronized (this.mergedBeanDefinitions) {
// 再次检查一次:DCL 双检查模式
if (!this.alreadyCreated.contains(beanName)) {
// Let the bean definition get re-merged now that we're actually creating
// the bean... just in case some of its metadata changed in the meantime.
// 从 mergedBeanDefinitions 中删除 beanName,并在下次访问时重新创建它。
clearMergedBeanDefinition(beanName);
// 添加到已创建 bean 集合中
this.alreadyCreated.add(beanName);
}
}
}
}

protected void clearMergedBeanDefinition(String beanName) {
RootBeanDefinition bd = this.mergedBeanDefinitions.get(beanName);
if (bd != null) {
bd.stale = true;
}
}

获取RootBeanDefinition

1
2
3
4
5
6
// 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
// 因为从 XML 配置文件中读取到的 Bean 信息是存储在GenericBeanDefinition 中的。但是,所有的 Bean 后续处理都是针对于 RootBeanDefinition 的,所以这里需要进行一个转换。
// 转换的同时,如果父类 bean 不为空的话,则会一并合并父类的属性。
RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
//检查是否为抽象类
checkMergedBeanDefinition(mbd, beanName, args);

调用 getMergedLocalBeanDefinition(String beanName) 方法,获取相对应的 BeanDefinition 对象。

1
2
3
4
5
6
7
8
9
10
11
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
// Quick check on the concurrent map first, with minimal locking.
// 快速从缓存中获取,如果不为空,则直接返回
RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
if (mbd != null && !mbd.stale) {
return mbd;
}
// 获取 RootBeanDefinition,
// 如果返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性
return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

调用 checkMergedBeanDefinition() 方法,检查给定的合并的 BeanDefinition 对象。

1
2
3
4
5
6
7
protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
throws BeanDefinitionStoreException {

if (mbd.isAbstract()) {
throw new BeanIsAbstractException(beanName);
}
}

处理依赖

如果一个 Bean 有依赖 Bean 的话,那么在初始化该 Bean 时是需要先初始化它所依赖的 Bean 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// AbstractBeanFactory.java

// 处理所依赖的 bean
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
// <1> 若给定的依赖 bean 已经注册为依赖给定的 bean
// 即循环依赖的情况,抛出 BeanCreationException 异常
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
// <2> 缓存依赖调用
registerDependentBean(dep, beanName);
try {
// <3> 递归处理依赖 Bean
getBean(dep);
} catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}

通过迭代的方式依次对依赖 bean 进行检测、校验。如果通过,则调用 getBean(String beanName) 方法,实例化依赖的 Bean 对象。

getDependsOn()

获取所有依赖,RootBeanDefinition继承自AbstractBeanDefinition所以委托给了父类处理:

1
2
3
4
5
6
7
//AbstractBeanDefinition.java
@Nullable
private String[] dependsOn;

public String[] getDependsOn() {
return this.dependsOn;
}
isDependent()

校验该依赖是否已经注册给当前 Bean 。

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
// DefaultSingletonBeanRegistry.java
protected boolean isDependent(String beanName, String dependentBeanName) {
synchronized (this.dependentBeanMap) {
return isDependent(beanName, dependentBeanName, null);
}
}

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
// alreadySeen 已经检测的依赖 bean
if (alreadySeen != null && alreadySeen.contains(beanName)) {
return false;
}
// 获取原始 beanName
String canonicalName = canonicalName(beanName);
// 获取当前 beanName 的依赖集合
Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
if (dependentBeans == null) {
return false;
}
// 存在,则证明存在已经注册的依赖
if (dependentBeans.contains(dependentBeanName)) {
return true;
}
// 递归检测依赖
for (String transitiveDependency : dependentBeans) {
if (alreadySeen == null) {
alreadySeen = new HashSet<>();
}
alreadySeen.add(beanName);
//递归
if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
return true;
}
}
return false;
}
registerDependentBean(dep, beanName)方法;

注册依赖记录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void registerDependentBean(String beanName, String dependentBeanName) {
// 获取 beanName
String canonicalName = canonicalName(beanName);

// 添加 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
synchronized (this.dependentBeanMap) {
Set<String> dependentBeans =
this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
if (!dependentBeans.add(dependentBeanName)) {
return;
}
}

// 添加 <dependentBeanName, <canonicalName>> 到 dependenciesForBeanMap 中
synchronized (this.dependenciesForBeanMap) {
Set<String> dependenciesForBean =
this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
dependenciesForBean.add(canonicalName);
}
}

getBean()方法

最后调用 getBean(String beanName) 方法,实例化依赖 Bean 对象。


十八、parentBeanFactory和依赖处理
http://www.muzili.ren/2022/06/11/parentBeanFactory和依赖处理/
作者
jievhaha
发布于
2022年6月11日
许可协议