从上篇文章中我们可以得知,如果从单例缓存中没有获取到单例bean,则会说明是下面俩种情况发生:
- 该bean的scope是singleton ,但是没有初始化完成
- 该bean的scope不是singleton
本篇文章就来进行这部分的分析,这里先讲循环依赖检测、parentBeanFactory与依赖处理,剩下的scope处理,主要在下一篇文章中讲解。
本文所分析的具体源码如下:
| 12
 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
 
 | 
 
 
 
 
 if (isPrototypeCurrentlyInCreation(beanName)) {
 throw new BeanCurrentlyInCreationException(beanName);
 }
 
 
 
 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) {
 
 return (T) parentBeanFactory.getBean(nameToLookup, args);
 } else if (requiredType != null) {
 
 return parentBeanFactory.getBean(nameToLookup, requiredType);
 } else {
 return (T) parentBeanFactory.getBean(nameToLookup);
 }
 }
 
 
 if (!typeCheckOnly) {
 markBeanAsCreated(beanName);
 }
 
 try {
 
 
 final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 checkMergedBeanDefinition(mbd, beanName, args);
 
 
 
 String[] dependsOn = mbd.getDependsOn();
 if (dependsOn != null) {
 for (String dep : dependsOn) {
 if (isDependent(beanName, dep)) {
 。。。。省略异常
 }
 
 registerDependentBean(dep, beanName);
 try {
 getBean(dep);
 } catch (NoSuchBeanDefinitionException ex) {
 省略异常
 }
 }
 }
 
 | 
这段代码主要处理流程如下:
- 检测当前beanName对应的bean是否是Prototype循环依赖,如果是,则抛出BeanCurrentlyInCreationException异常。
- 如果beanDefinitionMap中不存在beanName对应的BeanDefinition,前面说过BeanFactory是有继承体系的,可以从父BeanFactory中获取,也即是上面尝试从parentBeanFactory中加载。
- 判断是否为类型检查,如果不是,需要标记处理。
- 从mergedBeanDefinitions中获取beanName对应的RootBeanDefinition,如果这个BeanDefinition是子Bean的话,则会合并父类的相关属性。
- 依赖处理,这里的依赖是指depend-on属性指定的依赖,和后面说道的内部依赖不一样。
检测当前bean是否是Prototype类型的循环依赖
在前面就提过,Spring只解决单例模式下的循环依赖,对于原型模式的循环依赖则是抛出BeanCurrentlyInCreationException异常,所以首先检查该beanName是否处于原型模式下的循环依赖。如下:
| 12
 3
 
 | if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);
 }
 
 | 
调用isPrototypeCurrentlyInCreation()判断当前bean是否正在创建,如下:
| 12
 3
 4
 5
 6
 
 | protected boolean isPrototypeCurrentlyInCreation(String beanName) {Object curVal = this.prototypesCurrentlyInCreation.get();
 return (curVal != null &&
 (curVal.equals(beanName) ||
 (curVal instanceof Set && ((Set<?>) curVal).contains(beanName))));
 }
 
 | 
其实检测逻辑和单例模式一样,一个集合存放着正在创建的bean,从该集合中进行判断即可,只不过单例模式的集合为Set全局共享,而原型模式的则是ThreadLocal,线程私有,这也比较好理解,因为原型毕竟在需要的时候在创建,而且每个线程处理不同的逻辑,所以需要不同的对象,因此用ThreadLocal拉保存当前线程对应的正在创建的bean实例。prototypesCurrentlyInCreation定义如下:
| 12
 
 | private final ThreadLocal<Object> prototypesCurrentlyInCreation = new NamedThreadLocal<>("Prototype beans currently in creation");
 
 | 
这里只是判断,你可能会疑惑这是什么时候加入进去的。后面再讲创建不同作用域的bean实例时会说到。
检查父类BeanFactory
若 containsBeanDefinition 中不存在beanName相对应的BeanDefinition,则从parentBeanFactory中获取,这个是因为BeanFactory是可以有集成体系。源码如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | 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) {
 
 return (T) parentBeanFactory.getBean(nameToLookup, args);
 }
 else {
 
 return parentBeanFactory.getBean(nameToLookup, requiredType);
 }
 }
 
 | 
整个过程较为简单,都是委托 parentBeanFactory的getBean()进行处理,只不过在获取之前对name进行简单的处理,主要是想获取原始的beanName,也就是传进来的name如下:
| 12
 3
 4
 5
 6
 7
 
 | protected String originalBeanName(String name) {String beanName = transformedBeanName(name);
 if (name.startsWith(FACTORY_BEAN_PREFIX)) {
 beanName = FACTORY_BEAN_PREFIX + beanName;
 }
 return beanName;
 }
 
 | 
transformedBeanName() 是对 name 进行转换,获取真正的 beanName,因为我们传递的可能是 aliasName(这个过程在上一篇博客中分析 transformedBeanName() 有详细说明),如果 name 是以 “&” 开头的,则加上 “&”,因为在 transformedBeanName() 将“&” 掉了,这里加上。
类型检查
参数 typeCheckOnly 是用来判断调用getBean()是否为类型检查获取bean。如果不是仅做类型检查则是创建bean,则需要调用markBeanAsCreated()记录:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | protected void markBeanAsCreated(String beanName) {
 if (!this.alreadyCreated.contains(beanName)) {
 
 synchronized (this.mergedBeanDefinitions) {
 
 if (!this.alreadyCreated.contains(beanName)) {
 
 
 clearMergedBeanDefinition(beanName);
 
 this.alreadyCreated.add(beanName);
 }
 }
 }
 }
 
 | 
获取RootBeanDefinition
| 1
 | final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
 | 
调用 getMergedLocalBeanDefinition() 获取相对应的 BeanDefinition,如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
 
 RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
 if (mbd != null) {
 return mbd;
 }
 
 
 return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
 }
 
 | 
首先直接从mergedBeanDefinitions缓存中获取相应的RootBeanDefinition,如果存在则直接返回,不存在则调用getMergedBeanDefinition()获取RootBeanDefinition,若获取的BeanDefinition为子BeanDefinition,则需要合并父类的相关属性。具体的合并过程这里就不细说,如果你感兴趣的话可以仔细研究。
处理depend-on依赖
如果一个bean有依赖bean的话,那么在初始化该bean时是需要先初始化它所依赖的bean。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | 
 String[] dependsOn = mbd.getDependsOn();
 if (dependsOn != null) {
 
 for (String dep : dependsOn) {
 
 if (isDependent(beanName, dep)) {
 。。。。异常
 }
 
 registerDependentBean(dep, beanName);
 try {
 
 getBean(dep);
 }
 catch (NoSuchBeanDefinitionException ex) {
 。。。。省略异常
 }
 }
 }
 
 | 
这段代码逻辑是:通过迭代的方式依次对依赖bean进行检测、校验,如果检测通过,则调用getBean()实例化依赖bean。
isDependent() 是校验是否存在循环依赖,也就是A->B,B->C,C->A这种情况。
| 12
 3
 4
 5
 
 | protected boolean isDependent(String beanName, String dependentBeanName) {synchronized (this.dependentBeanMap) {
 return isDependent(beanName, dependentBeanName, null);
 }
 }
 
 | 
同步加锁给dependentBeanMap对象,然后调用isDependent()校验。dependentBeanMap对象保存的是依赖之间的映射关系:beanName–>依赖beanName的集合
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | private boolean isDependent(String beanName, String dependentBeanName,@Nullable Set<String> alreadySeen) {
 if (alreadySeen != null && alreadySeen.contains(beanName)) {
 return false;
 }
 String canonicalName = canonicalName(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()将该依赖进行记录,便于在销毁依赖bean之前对其进行销毁。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | public void registerDependentBean(String beanName, String dependentBeanName) {String canonicalName = canonicalName(beanName);
 
 synchronized (this.dependentBeanMap) {
 Set<String> dependentBeans =
 this.dependentBeanMap.computeIfAbsent(canonicalName,
 k -> new LinkedHashSet<>(8));
 if (!dependentBeans.add(dependentBeanName)) {
 return;
 }
 }
 
 synchronized (this.dependenciesForBeanMap) {
 Set<String> dependenciesForBean =
 this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName,
 k -> new LinkedHashSet<>(8));
 dependenciesForBean.add(canonicalName);
 }
 }
 
 | 
其实将就是该映射关系保存到两个集合中:dependentBeanMap、dependenciesForBeanMap。
最后调用getBean()实例化依赖bean。
至此,加载bean的第二个部分也分析完毕了,下篇开始分析第三个部分:不同作用域bean的创建。