Spring源码阅读之循环引用

一、前言

Spring循环依赖 是面试考点之一。面试官可以深挖面试者对 Spring 关于 Bean的生命周期 掌握情况。 Spring循环依赖 也是 Spring 难点之一,逻辑比较绕,需要对 Spring Bean 的生命周期了如指掌。

二、什么是循环依赖?

Spring源码阅读之循环引用

简单,就是A对象依赖了B对象,B对象依赖了A对象。

@Component
public class A {
	@Autowired
	B b;
}
复制代码
@Component
public class B {
	@Autowired
	A a;
}
复制代码

三、Spring是如何处理循环依赖?

3.1 使用文字描述具体循环依赖的两个Bean的生命周期流程

A 生命周期
1. class文件
2. 通过beanName去缓存中获取对象。一开始,单例池没有,且a也没有处于正在创建集合中,所以不会去二级缓存、三级缓存拿对象,相关代码[标记①]
3. 把对象放到正在创建集合中(beforeSingletonCreation(beanName);) 相关代码[标记②]
4. 通过反射实例化对象(createBeanInstance();) 相关代码[标记③]
5. 添加对象工厂到二级缓存中 相关代码[标记④]
6. 属性填充。在这里发现需要B对象,从单例池获取B->null->且b也没有处于正在创建集合中->实例化B且完成B的生命周期 相关代码[标记⑤]
    wait for b init...
7. 初始化   相关代码[标记⑥]
8. 从二级缓存中获取Bean  相关代码[标记⑦]
9. 添加到单例池 相关代码[标记⑥]

B 生命周期
1. class文件
2. 通过beanName去缓存中获取对象。一开始,单例池没有,且a也没有处于正在创建集合中,所以不会去二级缓存、三级缓存拿
3. 把对象放到正在创建集合中(beforeSingletonCreation(beanName);)
    (singletonObject = singletonFactory.getObject();)
4. 通过反射实例化对象(createBeanInstance();)
5. 添加对象工厂到二级缓存中
6. 属性填充。在这里发现需要A对象,从单例池获取A->null->此时a在正在创建集合中->从三级缓存中获取对象(如果a存在切面,则返回代理对象),将对象放至二级缓存,删除三级缓存
7. 初始化
8. 从二级缓存中获取Bean
9. 添加到单例池
复制代码
Spring源码阅读之循环引用

3.2 为什么需要三级缓存来解决循环依赖呢?

三级缓存定义及作用

  • 一级缓存: singletonObjects 。存储已走完 Spring 生命周期的 Bean 。注意, 对象Bean 在Spring的世界是完全两个概念。通过反射实例化的叫对象,此时这个对象并未完成 Spring 的生命周期流程(如后置处理器等), Bean 则表示已经完成 Spring 整个生命周期流程。
  • 二级缓存: earlySingletonObjects 。存储已实例化(通过反射创建的对象)但是未走完 Spring 生命周期流程的对象。
  • 三级缓存: singletonFactories 。存储 对象工厂 。目的是在适当的时候通过对象工厂生成 AOP 代理对象。

如何解决

  1. 通过提前暴露自己的方式(将自己加入三级缓存)让依赖者注入,从而不会导致死循环,可以走完剩下流程。
  2. 暴露对象工厂目的是为了完成 AOP 代理。对象工厂清楚如何创建对象的AOP代理,但是不会立马创建,而是到合适的时机进行 AOP 代理对象的创建。
  3. 二级缓存存 在的目的之一是保证对象只有一次 AOP 代理。当调用三级缓存的 getObject() 方法返回的对象会存入二级缓存,这样,当接下来的依赖者调用的时候, 会先判断 二级缓存 是否有目标对象,如果存在直接返回。

3.3 重要代码片段

代码① – getSingleton

// DefaultSingletonBeanRegistry#getSingleton
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // 从一级缓存中获取bean,即单例池
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        synchronized (this.singletonObjects) {
            // 从二级缓存中获取对象
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                // 从三级缓存获取对象工厂
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}
复制代码

代码② – beforeSingletonCreation

// DefaultSingletonBeanRegistry#beforeSingletonCreation
protected void beforeSingletonCreation(String beanName) {
    // 1.inCreationCheckExclusions: 判断当前对象是否存在 [被剔除] 集合对象中 注解 excludeFilters=xx
    // 2.singletonsCurrentlyInCreation: 将当前对象添加 [正在创建单例Bean] 集合中
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}
复制代码

代码③ – createBeanInstance

// AbstractAutowireCapableBeanFactory#createBeanInstance
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    // 如果为自动装配,则推断出来各种候选的构造方法
    Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
        mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
        // 利用推断出来的修行构造方法去实例化对象。如果使用构造器注入,这里直接返回
        return autowireConstructor(beanName, mbd, ctors, args);
    }
    ctors = mbd.getPreferredConstructors();
    if (ctors != null) {
        // 利用推断出来的候选构造方法去实例化对象
        return autowireConstructor(beanName, mbd, ctors, null);
    }

    // No special handling: simply use no-arg constructor.
    // 如果没有推断出合适的构造方法(或者没有提供特殊的构造方法),则使用默认的构造方法
    return instantiateBean(beanName, mbd);
}
复制代码

代码④ – addSingletonFactory

// DefaultSingletonBeanRegistry#addSingletonFactory
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);
        }
    }
}
复制代码

代码⑤ – populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        // 这里会有三个后置处理器,分别是:
        // 		1、ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
        // 		2、AutowiredAnnotationBeanPostProcessor
        // 		3、CommonAnnotationBeanPostProcessor
        // AutowiredAnnotationBeanPostProcessor: 解析@Autowire属性注入
        for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
            // 属性自动注入主要使用 AutowiredAnnotationBeanPostProcessor后置处理器
            PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
            if (pvsToUse == null) {
                if (filteredPds == null) {
                    filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                }
                pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    return;
                }
            }
            pvs = pvsToUse;
        }
    }
}
复制代码

代码⑥ – initializeBean

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
            invokeAwareMethods(beanName, bean);
            return null;
        }, getAccessControlContext());
    }
    else {
        // 4-1、执行Aware (BeanNameAware、BeanClassLoaderAware 、BeanFactoryAware)
        invokeAwareMethods(beanName, bean);
    }

    Object wrappedBean = bean;
    if (mbd == null || !mbd.isSynthetic()) {
        // 4.2 初始化前
        // △△ 执行Bean后置处理器(lifeCycle Callback)
        // 重写这个方法[postProcessBeforeInitialization]则会在这里被调用
        // lifeCycle callback init by annotation
        wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
    }

    try {
        // 4.3、初始化 [InitializingBean]
        // lifeCycle callback init by interface.
        invokeInitMethods(beanName, wrappedBean, mbd);
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
            (mbd != null ? mbd.getResourceDescription() : null),
            beanName, "Invocation of init method failed", ex);
    }


    if (mbd == null || !mbd.isSynthetic()) {
        // 4.4、初始化后
        // 完成AOP,生成动态代理; 事件发布; 监听
        wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
    }

    return wrappedBean;
}
复制代码

代码⑦ – doCreateBean

// AbstractAutowireCapableBeanFactory#doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
if (earlySingletonExposure) {
    // 在解决循环依赖时,获取beanName从二级缓存中获取
    Object earlySingletonReference = getSingleton(beanName, false);
    if (earlySingletonReference != null) {
        if (exposedObject == bean) {
            exposedObject = earlySingletonReference;
        }
        ...
    }
}
...
复制代码

代码⑧ – getSingleton

// DefaultSingletonBeanRegistry#getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null) {
        // 把当前对象放到 [正在创建] 的集合(singletonsCurrentlyInCreation)当中
        beforeSingletonCreation(beanName);
        
        // getObject方法会调用AbstractAutowireCapableBeanFactory的createBean方法
        singletonObject = singletonFactory.getObject();
        
        //添加到单例池
        addSingleton(beanName, singletonObject);
    }
}
复制代码

四、不同注入方式与循环依赖关系

依赖注入方式 循环依赖能否被解决
均采用setter方法注入
均采用构造器注入 不能
A中注入B的方式为setter方法,B中注入A的方式为构造器
A中注入B的方式为构造器,B中注入A的方式为setter方法 不能

注: A 先创建。

小结:

  1. 主对象(具备循环依赖且最先加载的类,简称A)不能通过 构造函数 的方法注入所依赖的Bean对象(简称B),而B不受限制,可以使用任意方式注入( setter、@Autowire、构造函数)
  2. 循环依赖中A对象不能使用 构造函数 注入的原因是在 AbstractAutowireCapableBeanFactory#createBeanInstance 方法中做类型推断时,如果推断是以构造方法实例B,则会直接调用“AbstractAutowireCapableBeanFactory#autowireConstructor ,该方法会通过调用 AbstractAutowireCapableBeanFactory#doCreateBean 创建对象,但是由于A对象没有提前暴露工厂(不给机会呀),所以只能一步步创建,但是走到代码 DefaultSingletonBeanRegistry#getSingleton beforeSingletonCreation 方法时,由于此时A正在创建集合,强行添加则会返回 false`,则抛出异常。相关代码③

如果解决循环依赖呢?

setter

原文 

https://juejin.im/post/5f0e5dd45188252e585845a5

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Spring源码阅读之循环引用

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址