Spring源码笔记-2.5 createBean

此方法交给了 AbstractBeanFactory 的子类 AbstractAutowireCapableBeanFactory 去实现。

并且不管这个bean是单例还是 prototype 还是其它 scope ,最终都是会走到此处,只是前后的一些验证、处理有区别。比如单例的就要先去缓存中获取,prototype 就不需要。

源码阅读到这里,我们已经习惯了一层一层剥。createBean 依然还是没有直接地把 bean 创建出来(当然我所期望的看到创建 bean 就是看到它的反射源码为止)。

createBean 的大致步骤为:

  1. 根据 RootBeanDefinition 来获取要创建 bean 的 class 。这 class 还有可能为 null。
  2. prepareMethodOverrides 。准备 override 方法,对 override 属性进行验证。
  3. 给后处理器一个机会来返回代理,替代真正的 bean.
  4. doCreateBean 创建真正的 bean 实例。

# prepareMethodOverrides

首先去温习一遍 lookup-method 和 replace-method 吧。博文

其实就是通过配置把原本 bean 中的某个方法给替代掉。

此处我们先只是确认一遍指定的替代方法存在于要生成的 bean 中。

顺带看一看这个方法有没有重载overload),做个标记。

# resolveBeforeInstantiation

经过一波预处理器InstantiationAwareBeanPostProcessor ,如果生产出了 bean,再经过一波后处理器。

一旦生产出 bean,则立即将此 bean 返回。

此处就是留下了一个拓展点,经过此方法之后,bean可能已经不是我们认为的 bean 了,而可能已经变成了一个经过处理的代理 bean 。

# 循环依赖

# 构造器循环依赖

如果是 prototype,无法解决,只能抛错。

代码在 AbstractBeanFactory : 256 doGetBean()

当创建 bean 时,首先去“当前创建 bean 池”查找是否当前 bean 正在创建,如果发现存在,则表示循环依赖了。抛出 BeanCurrentlyInCreationExcetion 。

当前创建 bean 池:

1
2
private final ThreadLocal<Object> prototypesCurrentlyInCreation =
      new NamedThreadLocal<Object>("Prototype beans currently in creation");

# setter 循环依赖

只能解决单例的情况。

在创建单例 bean 时,提前暴露刚完成构造器但未完成其他步骤(如 setter 注入)的 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
24
25
26
27
if (earlySingletonExposure) {
   if (logger.isDebugEnabled()) {
      logger.debug("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
   }
   addSingletonFactory(beanName, new ObjectFactory<Object>() {
      @Override
      public Object getObject() throws BeansException {
        //注意这里返回的是 早期引用
         return getEarlyBeanReference(beanName, mbd, bean);
      }
   });
}

	protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
		Assert.notNull(singletonFactory, "Singleton factory must not be null");
		synchronized (this.singletonObjects) {
			if (!this.singletonObjects.containsKey(beanName)) {
              //单例工厂注册
				this.singletonFactories.put(beanName, singletonFactory);
              //早期单例移出
				this.earlySingletonObjects.remove(beanName);
              //注册单例加入
				this.registeredSingletons.add(beanName);
			}
		}
	}

简单地记一下这里解决步骤:

testA 先创建,并且暴露一个工厂出去,进行 setter 注入 testB.

testB 创建,并且暴露一个工厂,进行 setter 注入 testA.

在这里想用 testA 时,由于发现提前暴露的工厂,从而在此处走了另一条路,使用此工厂来创建 testA ,在此处解决了循环问题。

再返回回去继续完成 testA 的 setter 注入。