本文主要说的是Spring是如何解决bean循环依赖的问题,循环依赖和生命周期交织在一起的。
生命周期图:
Spring容器初始化时会读取 我们配置bean的信息。然后再一个一个的创建:
DefaultListableBeanFactory.class:
public void preInstantiateSingletons() throws BeansException {
//beanNames中包含了Spring中所有待创建bean的名称。
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
for (String beanName : beanNames) {
……
//这里调用getBean不是为了获取bean,没有接收getBean的返回值。而是为了确保 要创建的bean都已创建
//getBean方法先会检测是否已经创建该bean,如果已创建则从缓存中获取,如果没有创建则新建。
getBean(beanName);
……
}
……
}
getBean方法:
public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args){
//调用doGetBean
return doGetBean(name, requiredType, args, false);
}
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) {
//name可能为别名,这里转换成真实的beanName。
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
// 从缓存中获取 bean 实例
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {//已经创建了bean实例
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
else {//还没有创建了bean实例
//如果是Prototype的循环依赖,直接报错。
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
}
// 检查父工厂中是否存在该bean.如果存在从父工厂获取。
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
……
}
if (!typeCheckOnly) {
//将beanName放入alreadyCreated集合中,表明该bean已经准备开始创建。
markBeanAsCreated(beanName);
}
try {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args);
// 保证当前bean所dependsOn的bean被初始化
// <bean name="***" class="***" depends-on="***" ></bean>
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
……
}
//创建bean实例 Create bean instance.
if (mbd.isSingleton()) {//单例Singleton
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
else if (mbd.isPrototype()) {//Prototype
……
}
else {
……
}
}
catch (BeansException ex) {
}
}
……
return (T) bean;
}
在getBean是一个空壳方法,getBean将任务交给了doGetBean去完成。在doGetBean中,在获取bean的过程中,首先判断缓存中是否有该bean,如果有使用缓存中的bean,如果没有再创建。
1、如何从缓存中获取bean?
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// 从 singletonObjects 获取实例,singletonObjects 中的实例都是准备好的 bean 实例,可以直接使用
Object singletonObject = this.singletonObjects.get(beanName);
// 判断 beanName 对应的 bean 是否正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
// 从 earlySingletonObjects 中获取提前曝光的 bean
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 获取相应的 bean 工厂
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 提前曝光 bean 实例(raw bean),用于解决循环依赖
singletonObject = singletonFactory.getObject();
// 将 singletonObject 放入缓存中,并将 singletonFactory 从缓存中移除
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
getSingleton(String) 是一个空壳方法,其主要逻辑在 getSingleton(String, boolean) 中。该方法逻辑比较简单,首先从 singletonObjects 缓存中获取 bean 实例。若未命中,再去 earlySingletonObjects 缓存中获取原始 bean 实例。如果仍未命中,则从 singletonFactory 缓存中获取 ObjectFactory 对象,然后再调用 getObject 方法获取原始 bean 实例的应用,也就是早期引用。获取成功后,将该实例放入 earlySingletonObjects 缓存中,并将 ObjectFactory 对象从 singletonFactories 移除。
2、如何创建bean?
这里只说单例bean的创建,其使用的是 getSingleton(String , ObjectFactory)方法:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
......
// 调用 getObject 方法创建 bean 实例
singletonObject = singletonFactory.getObject();
newSingleton = true;
if (newSingleton) {
// 添加 bean 到 singletonObjects 缓存中,并从其他集合中将 bean 相关记录移除
addSingleton(beanName, singletonObject);
}
......
// 返回 singletonObject
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
// 将 <beanName, singletonObject> 映射存入 singletonObjects 中
this.singletonObjects.put(beanName, (singletonObject != null ? singletonObject : NULL_OBJECT));
// 从其他缓存中移除 beanName 相关映射
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
上面的代码中包含两步操作,第一步操作是调用 getObject 创建 bean 实例,第二步是调用 addSingleton 方法将创建好的 bean 放入缓存中。代码逻辑并不复杂,相信大家都能看懂。那么接下来我们继续往下看,getObject 会调createBean,createBean会调doCreateBean 中。doCreateBean 如下:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args){
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
// 创建 bean 对象,并将 bean 对象包裹在 BeanWrapper 对象中返回,这里的bean的属性依赖还没有注入。
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
//从BeanWrapper中获取bean
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
//earlySingletonExposure 用于表示是否”提前暴露“原始对象的引用,用于解决循环依赖。对于单例 bean,该变量一般为 true。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//earlySingletonExposure为true时,需要缓存
if (earlySingletonExposure) {
//bean 会被封装在ObjectFactory中,可以通过ObjectFactory的getObject获取。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//注入bean所依赖的对象,setter方式。
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
}
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
String[] dependentBeans = getDependentBeans(beanName);
Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);
for (String dependentBean : dependentBeans) {
if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
actualDependentBeans.add(dependentBean);
}
}
if (!actualDependentBeans.isEmpty()) {
throw new BeanCurrentlyInCreationException(beanName,
"Bean with name '" + beanName + "' has been injected into other beans [" +
StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
"] in its raw version as part of a circular reference, but has eventually been " +
"wrapped. This means that said other beans do not use the final version of the " +
"bean. This is often the result of over-eager type matching - consider using " +
"'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
}
}
}
}
// Register bean as disposable.
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
1、创建bean:
//创建bean的实例。
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
……
//如果指定了有参的构造函数。
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null ||
mbd.getResolvedAutowireMode() == RootBeanDefinition.AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//有参构造函数,参数会通过getBean方法从Spring容器中获取。
return autowireConstructor(beanName, mbd, ctors, args);
}
//默认使用无参的构造函数。
return instantiateBean(beanName, mbd);
}
createBeanInstance默认会通过无参的构造方法创建bean。
2、将bean缓存
//bean 会被封装在ObjectFactory中,可以通过ObjectFactory的getObject获取。
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
//再次确认该bean是否已经创建完成(实例+属性注入)。
if (!this.singletonObjects.containsKey(beanName)) {//未创建完成,已实例化。
this.singletonFactories.put(beanName, singletonFactory);//bean会被封装在ObjectFactory中,并放入singletonFactories中。
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
3、依赖属性注入
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
……
}
populateBean方法内容比较多,其核心就是A依赖B,那么就通过getBean方法获取B,在设置到A中。
4、初始化bean
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
//检测Aware接口并设置相关依赖。
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用bean 的后置处理器中的 beforeInitialization。
wrappedBean = this.applyBeanPostProcessorsBeforeInitialization(bean, beanName);
}
try {
//这个包含了InitializingBean.afterPropertiesSet和 init-method的调用
this.invokeInitMethods(beanName, wrappedBean, mbd);
} catch () {}
if (mbd == null || !mbd.isSynthetic()) {
//调用bean 的后置处理器中的 AfterInitialization
wrappedBean = this.applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}