继续分析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
//假设我们在一个循环引用中,如果我们已经创建了这个bean实例,则会失败:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}

// 获取父bean工厂,其用于bean继承支持。
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查这个工厂中是否存在bean定义。
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 未找到->检查父类。
//确定原始bean名称,将本地定义的别名解析为规范名称。
String nameToLookup = originalBeanName(name);
//如果父bean工厂instanceof AbstractBeanFactory
if (parentBeanFactory instanceof AbstractBeanFactory) {
//从父工厂中获取bean
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 使用显式args委托给父对象。
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// 没有args ->委托给标准getBean方法。
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
//以上条件都不满足,直接根据要检索的bean的名称获取
return (T) parentBeanFactory.getBean(nameToLookup);
}
}

// 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
//将指定的bean标记为已经创建(或即将创建)。
markBeanAsCreated(beanName);
}

1、检测

在上一篇文章中分析到,尝试从单例缓存中获取原始实例时,通过判断集合Set singletonsCurrentlyInCreation中是否正在创建这个bean,并解决循环依赖。
原型模式的循环依赖则直接抛出BeanCurrentlyInCreationException,是通过判断ThreadLocal prototypesCurrentlyInCreation中是否存在正在创建的beanName。

1
2
3
4
5
6
7
8
9
10
11
12
13
//假设我们在一个循环引用中,如果我们已经创建了这个bean实例,则会失败:
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
//返回指定的原型bean是否正在创建中(在当前线程中)。
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
Object curVal = this.prototypesCurrentlyInCreation.get();
return (curVal != null &&
(curVal.equals(beanName) || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
}
//当前正在创建的bean的名称。
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
new NamedThreadLocal<>("Prototype beans currently in creation");

2、父类BeanFactory

首先检查当前的工厂中是否存在此bean的BeanDefinition,如果不存在的话,从父类BeanFactory中获取。

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
 // 获取父bean工厂,其用于bean继承支持。
BeanFactory parentBeanFactory = getParentBeanFactory();
// 检查这个工厂中是否存在bean定义。
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// 未找到->检查父类。
//确定原始bean名称,将本地定义的别名解析为规范名称。
String nameToLookup = originalBeanName(name);
//如果父bean工厂instanceof AbstractBeanFactory
if (parentBeanFactory instanceof AbstractBeanFactory) {
//从父工厂中获取bean
return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
nameToLookup, requiredType, args, typeCheckOnly);
} else if (args != null) {
// 使用显式args委托给父对象。
return (T) parentBeanFactory.getBean(nameToLookup, args);
} else if (requiredType != null) {
// 没有args ->委托给标准getBean方法。
return parentBeanFactory.getBean(nameToLookup, requiredType);
} else {
//以上条件都不满足,直接根据要检索的bean的名称获取
return (T) parentBeanFactory.getBean(nameToLookup);
}
}
/**
* 检查这个bean工厂是否包含具有给定名称的bean定义。
* 不考虑此工厂可能参与的任何层次结构。
* 当没有找到缓存的单例实例时,由{@code containsBean}调用。
* 根据具体bean工厂实现的性质,此操作可能很昂贵(例如,由于外部注册中心中的目录查找)。
* 然而,对于可列表bean工厂,这通常只是一个本地哈希查找:因此,该操作是那里的公共接口的一部分。
* 在这种情况下,相同的实现可以用于此模板方法和公共接口方法。
*/
protected abstract boolean containsBeanDefinition(String beanName);
//确定原始bean名称,将本地定义的别名解析为规范名称。
protected String originalBeanName(String name) {
// 返回bean名称,在必要时去掉工厂的取消引用前缀,并将别名解析为规范名称。
String beanName = transformedBeanName(name);
//如果name以"&"开头,补上"&"
if (name.startsWith(FACTORY_BEAN_PREFIX)) {
beanName = FACTORY_BEAN_PREFIX + beanName;
}
return beanName;
}

最终都是委托给父类BeanFactory的getBean处理了。

3、类型检查

1
2
3
4
5
 // 如果不是仅仅做类型检查则是创建bean,这里需要记录
if (!typeCheckOnly) {
//将指定的bean标记为已经创建(或即将创建)。
markBeanAsCreated(beanName);
}

如果是创建bean,需要标记一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//至少已经创建过一次的bean的名称。
private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
// 从bean名称映射到合并的RootBeanDefinition。
private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
//将指定的bean标记为已经创建(或即将创建)。允许bean工厂为重复创建指定的bean优化缓存。
protected void markBeanAsCreated(String beanName) {
//至少已经创建过一次的bean
if (!this.alreadyCreated.contains(beanName)) {
//锁定mergedBeanDefinitions,表示:从bean名称映射到合并的RootBeanDefinition。
synchronized (this.mergedBeanDefinitions) {
//再检测一次
if (!this.alreadyCreated.contains(beanName)) {
// 现在我们正在创建bean,让bean定义重新合并…
// 以防它的元数据在此期间发生变化。
clearMergedBeanDefinition(beanName);
// 添加到已创建bean 集合中
this.alreadyCreated.add(beanName);
}
}
}
}

tencent.jpg

文章作者: ClawHub
文章链接: https://clawhub.github.io/2019/08/09/%E5%B8%B8%E7%94%A8%E6%A1%86%E6%9E%B6/Spring/Spring-IOC%E5%8A%A0%E8%BD%BDBean%E3%80%90%E4%B8%89%E3%80%91parentBeanFactory%E4%B8%8E%E5%88%9B%E5%BB%BA%E6%A0%87%E8%AE%B0/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 ClawHub的技术分享