首先bean是spring中对一个完整对象的定义,而对象是java中的一个定义。一个完成的bean肯定是一个对象,一个对象有可能不是一个完成的bean。
参考博客:https://www.jianshu.com/p/8bb67ca11831
循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图:
一级缓存:
/** 保存所有的singletonBean的实例 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);
二级缓存:
/** 保存所有早期创建的Bean对象,这个Bean还没有完成依赖注入 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
三级缓存:
/** singletonBean的生产工厂*/
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
调用
public Object getSingleton(String beanName) {
return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
//如果一级缓存中获取bean获取不到,并且对象正在创建中,则从二级缓存earlySingletonObjects中获取
//isSingletonCurrentlyInCreation()判断当前单例bean是否正在创建中,
// 也就是没有初始化完成(比如A的构造器依赖了B对象所以得先去创建B对象, 或
// 则在A的populateBean过程中依赖了B对象,得先去创建B对象,这时的A就是处于创建中的状态。)
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
//如果还是获取不到且允许singletonFactories通过getObject()获取,
// 就从三级缓存singletonFactory.getObject()(三级缓存)获取
//allowEarlyReference是否允许从singletonFactories中通过getObject拿到对象
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//如果获取到了则从singletonFactories中移除,并放入earlySingletonObjects中,也就是从三级缓存移动到了二级缓存
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
//返回单例对象
return singletonObject;
}
执行createBean方法
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
if (logger.isDebugEnabled()) {
logger.debug("Creating instance of bean '" + beanName + "'");
}
RootBeanDefinition mbdToUse = mbd;
// Make sure bean class is actually resolved at this point, and
// clone the bean definition in case of a dynamically resolved Class
// which cannot be stored in the shared merged bean definition.
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// Prepare method overrides.
try {
mbdToUse.prepareMethodOverrides();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
beanName, "Validation of method overrides failed", ex);
}
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isDebugEnabled()) {
logger.debug("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
// A previously detected exception with proper bean creation context already,
// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException(
mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
}
}
执行docreateBean方法
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
//BeanWrapper提供设置和获取属性值(单独或批量),获取属性描述符和查询属性以确定它们是可读还是可写的功能
BeanWrapper instanceWrapper = null;
//单例的情况下尝试从factoryBeanInstanceCache获取 instanceWrapper
if (mbd.isSingleton()) {
//map的remove方法返回值,则是移除的key对应的value
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
//如果没有则需要自己创建
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
//如果不是NullBean,则将resolvedTargetType 属性设置为当前的WrappedClass
if (beanType != NullBean.class) {
mbd.resolvedTargetType = beanType;
}
// Allow post-processors to modify the merged bean definition.
// 这边主要是寻找几个meta,@PostConstruct,@Autowire,@Value,@Resource,@PreDestory等
synchronized (mbd.postProcessingLock) {
if (!mbd.postProcessed) {
try {
applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Post-processing of merged bean definition failed", ex);
}
mbd.postProcessed = true;
}
}
// Eagerly cache singletons to be able to resolve circular references
// even when triggered by lifecycle interfaces like BeanFactoryAware.
//如果当前bean是单例,且支持循环依赖,且当前bean正在创建,通过往singletonFactories添加一个objectFactory,
//这样后期如果有其他bean依赖c该bean 可以从singletonFactories获取到bean,getEarlyBeanReferene可以对返回的bean进行修改,这边目前除了可能会返回动态代理对象 其他的都是直接返回bean
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
//提前曝光bean
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//这里是解决循环依赖的关键,发生在createBeanInstance之后
/*也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,
虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),
所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用*/
// see :DefaultSingletonBeanRegistry.addSingletonFactory
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
//对bean进行属性填充;其中,可能存在依赖于其他bean的属性,则会递归初始化依赖的bean实例
populateBean(beanName, mbd, instanceWrapper);
//初始化bean, 处理 bean 初始化完成后的各种回调,例如init-method 配置,BeanPostProcessor接口
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
catch (Throwable ex) {
if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
throw (BeanCreationException) ex;
}
else {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
}
}
// 如果已经提交曝光了bean,那么就从缓存中获取bean,尝试从缓存获取该bean(一般存放在singletonFactories对象通过
// 调用getObject 把对象存入earlySingletonObjects),分别从singletonObjects和earlySingletonObjects获取对象
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//如果获取到对象了
if (earlySingletonReference != null) {
//当exposedObject (初始化之后的bean等于原始的bean,说明不是proxy),则把缓存中的bean赋值给exposedObject
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
//检测该bean的dependon的bean是否都已经初始化好了
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.
//注册DisposableBean
try {
registerDisposableBeanIfNecessary(beanName, bean, mbd);
}
catch (BeanDefinitionValidationException ex) {
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
}
return exposedObject;
}
执行createBeanInstance方法
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
// Make sure bean class is actually resolved at this point.
//解析class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//如果beanclass不为空,且beanclass不是public 且没有权限访问构造函数和方法则抛出异常
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
}
//Supplier类似于factoryBean,然后从Supplier.get()的bean,并把bean包装成BeanWrapper,然后初始化BeanWrapper
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
// 1.如果存在工厂方法则使用工厂方法实例化bean对象
if (mbd.getFactoryMethodName() != null) {
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// Shortcut when re-creating the same bean...
// 一个类可能有多个构造器,所以Spring得根据参数个数、类型确定需要调用的构造器
// 在使用构造器创建实例后,Spring会将解析过后确定下来的构造器或工厂方法保存在缓存中,避免再次创建相同bean时再次解析
//resolved: 构造函数或工厂方法是否已经解析过
boolean resolved = false;
// autowireNecessary: 是否需要自动注入(即是否需要解析构造函数参数)
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
//说明曾经解析过构造函数或者factoryMethod
if (mbd.resolvedConstructorOrFactoryMethod != null) {
// 2.1 如果resolvedConstructorOrFactoryMethod缓存不为空,则将resolved标记为已解析
resolved = true;
// 2.2 根据constructorArgumentsResolved判断是否需要自动注入
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
//如果已经解析过了则按照逻辑选择
if (resolved) {
// 3.如果已经解析过,则使用resolvedConstructorOrFactoryMethod缓存里解析好的构造函数方法
if (autowireNecessary) {
// 3.1 需要自动注入,则执行构造函数自动注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
// 3.2 否则使用默认的构造函数进行bean的实例化
return instantiateBean(beanName, mbd);
}
}
// Candidate constructors for autowiring?
// 说明是第一次创建该bean 根据SmartInstantiationAwareBeanPostProcessor获取构造函数,
// 目前看基本上都是空的实现,除了AutowiredAnnotationBeanPostProcessor
// 4.应用后置处理器SmartInstantiationAwareBeanPostProcessor,拿到bean的候选构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
// 解析的构造器不为空 || 注入类型为构造函数自动注入 || bean定义中有构造器参数 || 传入参数不为空
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//构造函数自动注入,开始生成实例
// 5.如果ctors不为空 || mbd的注入方式为AUTOWIRE_CONSTRUCTOR || mdb定义了构造函数的参数值 || args不为空,则执行构造函数自动注入
return autowireConstructor(beanName, mbd, ctors, args);
}
// No special handling: simply use no-arg constructor.
// 使用默认构造器,采用普通的方式生成实例
// 6.没有特殊处理,则使用默认的构造函数进行bean的实例化
return instantiateBean(beanName, mbd);
}
A放入三级缓存中是一个factory对象,是因为spring目前还无法判断,A对象在后续是否存在循环依赖,所以factory对象的目的在于,如果发生了循环依赖,则需要创建被增强的对象,而为什么又是被增强的对象呢,因为,我记得spring对bean的增强统一在后置处理中,但是由于被依赖,所以必须提前创建好被增强的对象,放入到二级缓存中。否则在程序运行中是代理对象A,而B拿到的对象却是普通对象A。
但是那跟放入二级缓存有啥关系呀,那是因为,如果不放入二级缓存中,那只能还是从三级缓存中获取,那么会再次触发aop增强:
doCreateBean方法中:
//提前曝光bean
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
//这里是解决循环依赖的关键,发生在createBeanInstance之后
/*也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,
虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),
所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用*/
// see :DefaultSingletonBeanRegistry.addSingletonFactory
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
所以,到最后创建完整之后,加入到一级缓存中
所以综上所述,解决循环依赖的关键点就是第三级缓存的存在。
因为A中构造器注入了B,那么A在关键的方法addSingletonFactory()之前就去初始化了B,导致三级缓存中根本没有A,所以会发生死循环,Spring发现之后就抛出异常了。至于Spring是如何发现异常的呢,本质上是根据Bean的状态给Bean进行mark,如果递归调用时发现bean当时正在创建中,那么久抛出循环依赖的异常即可