千家信息网

如何用spring源码剖析spring bean循环依赖

发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇文章给大家分享的是有关如何用spring源码剖析spring bean循环依赖,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。spri
千家信息网最后更新 2026年11月02日如何用spring源码剖析spring bean循环依赖

本篇文章给大家分享的是有关如何用spring源码剖析spring bean循环依赖,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

spring bean循环依赖

spring bean循环依赖应该是spring 源码中比较难的一块知识了,下面我们结合代码还有时序图,来进行分析,看下spring 是如何优雅的处理spring bean的循环依赖的。

什么是bean的循环依赖

我们都知道spring的IOC 和DI,它可以帮助我们创建对象,并且可以帮我们自动注入需要spring管理的对象。然后会存在一种这样的情况,在对象 A 中需要依赖 B,而在对象 B 中有又依赖 A,当然可以有更多的对象依赖,他们之间会组成了一个闭环,如下图 在spring 初始化bean A的时候发现bean A依赖于bean B,然后去实例化bean B,实例化bean B的时候又发现bean B依赖于bean A...,这样陷入了一个无限循环的过程中,最终可能会导致内存溢出。当然,这只是我们的一个设想,spring当然不会让这样的事情发生。spring提供一个很优雅的方式来帮我们解决了bean之间循环依赖的问题,通过引入三级缓存机制来解决。 另外再说一点,不是所有的循环依赖spring 都可以解决,以下两种方式spring也是无法解决的

  • 依赖是通过构造方法实现的

  • scope 为prototype,也就是原型的情况

在正式开始之前,我们再说下spring的三级缓存以及定义 先来看下代码中是如何定义的

     /** Cache of singleton objects: bean name to bean instance. */        private final Map singletonObjects = new ConcurrentHashMap<>(256);        /** Cache of singleton factories: bean name to ObjectFactory. */        private final Map> singletonFactories = new HashMap<>(16);        /** Cache of early singleton objects: bean name to bean instance. */        private final Map earlySingletonObjects = new HashMap<>(16);
  • singletonObjects 一级缓存, 用于存放完全初始化之后的bean,也就是说,所有的准备工作已经完成了,可以拿出来使用了

  • earlySingletonObjects 二级缓存,存放原始的bean对象,这时候bean只是实例化完成,还没有进行属性设置等工作

  • singletonFactories 三级缓存,存放只是实例化,还没有进行其它任何操作的bean对象

下面我们结合代码来做进一步的分析

依赖代码

bean A

创建类BeanA,然后通过set注入BeanB

public class BeanA {        private BeanB beanB;        public void setBeanB(BeanB beanB) {                this.beanB = beanB;        }}

bean B

创建类BeanB,然后通过set注入BeanA

public class BeanB {        private BeanA beanA;        public void setBeanA(BeanA beanA) {                this.beanA = beanA;        }}

配置文件applicationContext.xml

将BeanA 和BeanB 交给spring来进行管理

                                                                        

测试代码

使用ClassPathXmlApplicationContext来初始化bean

public class BeanTest {        public static void main(String[] args) {                ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");                Object beanA = applicationContext.getBean("beanA");                System.out.println(beanA);        }}

源码分析

循环依赖时序图

在分析源码前我们先来看下spring 循环依赖的时序图,对于后面我们分析源码会有很大的帮助 原始文件可以从这里下载

ClassPathXmlApplicationContext.java

我们调用了ClassPathXmlApplicationContext的带参构造方法,最终调用了下面的构造。这里完成了三件事:

  1. super(parent)初始化父类

  2. setConfigLocations(configLocations)设置本地的配置信息

  3. refresh()完成spring容器的初始化

这里我们重点观察第三个方法,因为spring bean的初始化是在这里完成的

        public ClassPathXmlApplicationContext(                        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)                        throws BeansException {                // 初始化父类                super(parent);                // 设置本地的配置信息                setConfigLocations(configLocations);                // 完成Spring容器的初始化                if (refresh) {                        refresh();                }        }

AbstractApplicationContext.java

上面说了,refresh方法是初始化spring容器的,所以这是一个核心方法。这里面包含beanFactory 和bean的初始化操作,因为方法比较多,对每个方法都进行了注释,不一一赘述了,这里我们重点关注finishBeanFactoryInitialization(),这个方法做了一下操作

  • 初始化所有剩下的非懒加载的单例bean

  • 初始化创建非懒加载方式的单例Bean实例(未设置属性)

  • 填充属性

  • 初始化方法调用(比如调用afterPropertiesSet方法、init-method方法)

  • 调用BeanPostProcessor(后置处理器)对实例bean进行后置处理 所以我们接下来看下这个方法

public void refresh() throws BeansException, IllegalStateException {                // 对象锁加锁                synchronized (this.startupShutdownMonitor) {                        //刷新前的预处理,表示在真正做refresh操作之前需要准备做的事情:                        prepareRefresh();                        /*                           获取BeanFactory;默认实现是DefaultListableBeanFactory                加载BeanDefition 并注册到 BeanDefitionRegistry                         */                        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();                        //BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器等)                        prepareBeanFactory(beanFactory);                        try {                                //BeanFactory准备工作完成后进行的后置处理工作                                postProcessBeanFactory(beanFactory);                                //实例化实现了BeanFactoryPostProcessor接口的Bean,并调用接口方法                                invokeBeanFactoryPostProcessors(beanFactory);                                //注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行                                registerBeanPostProcessors(beanFactory);                                //初始化MessageSource组件(做国际化功能;消息绑定,消息解析);                                initMessageSource();                                //初始化事件派发器                                initApplicationEventMulticaster();                                //子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器                                onRefresh();                                //注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean                                registerListeners();                                /*  Instantiate all remaining (non-lazy-init) singletons.                                        初始化所有剩下的非懒加载的单例bean                                        初始化创建非懒加载方式的单例Bean实例(未设置属性)                    填充属性                    初始化方法调用(比如调用afterPropertiesSet方法、init-method方法)                    调用BeanPostProcessor(后置处理器)对实例bean进行后置处理                                 */                                finishBeanFactoryInitialization(beanFactory);                                //完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)                                finishRefresh();                        } catch (BeansException ex) {                                destroyBeans();                                cancelRefresh(ex);                                throw ex;                        } finally {                                resetCommonCaches();                        }                }        }

这个方法的最后调用了beanFactory的preInstantiateSingletons()方法,接下继续跟踪preInstantiateSingletons()方法

      protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {                if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&                                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {                        beanFactory.setConversionService(                                        beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));                }                if (!beanFactory.hasEmbeddedValueResolver()) {                        beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));                }                // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.                String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);                for (String weaverAwareName : weaverAwareNames) {                        getBean(weaverAwareName);                }                // Stop using the temporary ClassLoader for type matching.                beanFactory.setTempClassLoader(null);                // Allow for caching all bean definition metadata, not expecting further changes.                beanFactory.freezeConfiguration();                // Instantiate all remaining (non-lazy-init) singletons.                // 实例化所有立即加载的单例bean                beanFactory.preInstantiateSingletons();        }

DefaultListableBeanFactory.java

preInstantiateSingletons()中获取了所有需要spring管理的bean的name,然后需要遍历,进行bean的创建,核心方法是getBean(beanName),根据获取到的bean name进行bean的初始化,所以接下来我们跟踪getBean(beanName)

public void preInstantiateSingletons() throws BeansException {                if (logger.isTraceEnabled()) {                        logger.trace("Pre-instantiating singletons in " + this);                }                // 获取所有bean的名字                List beanNames = new ArrayList<>(this.beanDefinitionNames);                // 触发所有非延迟加载单例bean的初始化,主要步骤为getBean                for (String beanName : beanNames) {                        RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);                        if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {                                if (isFactoryBean(beanName)) {                                        Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);                                        // 如果是FactoryBean则加&                                        if (bean instanceof FactoryBean) {                                                final FactoryBean factory = (FactoryBean) bean;                                                boolean isEagerInit;                                                if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {                                                        isEagerInit = AccessController.doPrivileged((PrivilegedAction)                                                                                        ((SmartFactoryBean) factory)::isEagerInit,                                                                        getAccessControlContext());                                                }                                                else {                                                        isEagerInit = (factory instanceof SmartFactoryBean &&                                                                        ((SmartFactoryBean) factory).isEagerInit());                                                }                                                if (isEagerInit) {                                                        getBean(beanName);                                                }                                        }                                }                                else {                                        // 实例化当前bean                                        getBean(beanName);                                }                        }                }                for (String beanName : beanNames) {                        Object singletonInstance = getSingleton(beanName);                        if (singletonInstance instanceof SmartInitializingSingleton) {                                final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;                                if (System.getSecurityManager() != null) {                                        AccessController.doPrivileged((PrivilegedAction) () -> {                                                smartSingleton.afterSingletonsInstantiated();                                                return null;                                        }, getAccessControlContext());                                }                                else {                                        smartSingleton.afterSingletonsInstantiated();                                }                        }                }        }

开始处理循环依赖

为了方便阅读删除了部分源码

上面方法中调用了getBean(),getBean()又调用了doGetBean(),经过前面的铺垫,其实到这里,才开始了真正的循环依赖相关的源码逻辑。 之前我们说过spring 的三级缓存,这里根据bean name先调用getSingleton(beanName)方法,getSingleton(beanName)方法中又调用了它的重载方法。我们先假设要去找的bean为beanA,spring先从一级缓存中去找我们要的beanA,找不到的话去二级缓存中去找,二级缓存还找不到去一级缓存中去拿,当然,因为刚加载,所以三级缓存中也是没有的。所以代码继续往下执行。

  public Object getBean(String name) throws BeansException {                return doGetBean(name, null, null, false);        }protected  T doGetBean(final String name, @Nullable final Class requiredType,                        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {                // 解析beanName 如果以&开头去掉&开头,如果是别名获取到真正的名字                final String beanName = transformedBeanName(name);                // 尝试从一二三级缓存中获取 bean                Object sharedInstance = getSingleton(beanName);                // 如果已经存在则返回                if (sharedInstance != null && args == null) {                        // 针对 FactoryBean 的处理                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);                } else {                        // 如果是prototype类型且开启允许循环依赖,则抛出异常                        if (isPrototypeCurrentlyInCreation(beanName)) {                                throw new BeanCurrentlyInCreationException(beanName);                        }                        try {                                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName)                                // 创建单例bean                                if (mbd.isSingleton()) {                                        sharedInstance = getSingleton(beanName, () -> {                                                try {                                                        // 创建 bean                                                        return createBean(beanName, mbd, args);                                                }                                                catch (BeansException ex) {                                                        destroySingleton(beanName);                                                        throw ex;                                                }                                        });                                        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);                                }                        }                }                return (T) bean;        }        public Object getSingleton(String beanName) {                return getSingleton(beanName, true);        }                protected Object getSingleton(String beanName, boolean allowEarlyReference) {                //先从一级缓存singletonObjects中拿                Object singletonObject = this.singletonObjects.get(beanName);                // isSingletonCurrentlyInCreation(beanName)判断当前单例bean是否正在创建中                if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {                        synchronized (this.singletonObjects) {                                //一级缓存没有从二级缓存earlySingletonObjects中去拿                                singletonObject = this.earlySingletonObjects.get(beanName);                                if (singletonObject == null && allowEarlyReference) {                                        //二级缓存没有从三级缓存singletonFactories去拿                                        ObjectFactory singletonFactory = this.singletonFactories.get(beanName);                                        if (singletonFactory != null) {                                                singletonObject = singletonFactory.getObject();                                                //三级缓存中有的话放入二级缓存中,同时从一级缓存中删除                                                this.earlySingletonObjects.put(beanName, singletonObject);                                                this.singletonFactories.remove(beanName);                                        }                                }                        }                }                return singletonObject;        }       

接着上面的doGetBean()方法往下走,又调用了getSingleton()的另一个重载方法,可以看到第二个参数是一个ObjectFactory接口,而这里spring采用了一个lambda表达式来实现了getObject()方法。调用传进来的lambda表达式singletonFactory.getObject(),进行bean的创建。

public Object getSingleton(String beanName, ObjectFactory singletonFactory) {                Assert.notNull(beanName, "Bean name must not be null");                synchronized (this.singletonObjects) {                        Object singletonObject = this.singletonObjects.get(beanName);                        if (singletonObject == null) {                                // 是否正在销毁,异常                                if (this.singletonsCurrentlyInDestruction) {                                        throw new BeanCreationNotAllowedException(beanName,                                                        "Singleton bean creation not allowed while singletons of this factory are in destruction " +                                                        "(Do not request a bean from a BeanFactory in a destroy method implementation!)");                                }                                if (logger.isDebugEnabled()) {                                        logger.debug("Creating shared instance of singleton bean '" + beanName + "'");                                }                                // 验证完要真正开始创建对象,先标识该bean正在被创建,因为spingbean创建过程复杂,步骤很多,需要标识                                beforeSingletonCreation(beanName);                                boolean newSingleton = false;                                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);                                if (recordSuppressedExceptions) {                                        this.suppressedExceptions = new LinkedHashSet<>();                                }                                try {                                        // 传进来的调用,lamda表达式使用                                        singletonObject = singletonFactory.getObject();                                        newSingleton = true;                                }                                catch (IllegalStateException ex) {                                        // Has the singleton object implicitly appeared in the meantime ->                                        // if yes, proceed with it since the exception indicates that state.                                        singletonObject = this.singletonObjects.get(beanName);                                        if (singletonObject == null) {                                                throw ex;                                        }                                }                                catch (BeanCreationException ex) {                                        if (recordSuppressedExceptions) {                                                for (Exception suppressedException : this.suppressedExceptions) {                                                        ex.addRelatedCause(suppressedException);                                                }                                        }                                        throw ex;                                }                                finally {                                        if (recordSuppressedExceptions) {                                                this.suppressedExceptions = null;                                        }                                        afterSingletonCreation(beanName);                                }                                if (newSingleton) {                                        addSingleton(beanName, singletonObject);                                }                        }                        return singletonObject;                }        }

接下来看下lambda表达式中的createBean(beanName, mbd, args)方法是如何实现的 createBean()中其实又调用了doCreateBean(),它才是真正干活的。这里首先调用对createBeanInstance(beanName, mbd, args)对beanA进行实例化,然后放入三级缓存中,接下来调用populateBean(beanName, mbd, instanceWrapper)对beanA进行属性填充,在我们这里其实就是填充beanB,我们继续看填充方法中做了什么

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {                // 拿到Bd                RootBeanDefinition mbdToUse = mbd;                //....                try {                        // 进入,真真正正创建bean                        Object beanInstance = doCreateBean(beanName, mbdToUse, args);                        if (logger.isTraceEnabled()) {                                logger.trace("Finished creating instance of bean '" + beanName + "'");                        }                        return beanInstance;                } catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {                        throw ex;                }        }protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {                // Instantiate the bean.                BeanWrapper instanceWrapper = null;                if (mbd.isSingleton()) {                        instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);                }                if (instanceWrapper == null) {                        // 创建 Bean 实例,仅仅调用构造方法,但是尚未设置属性                        instanceWrapper = createBeanInstance(beanName, mbd, args);                }                        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&                                isSingletonCurrentlyInCreation(beanName));                if (earlySingletonExposure) {                        if (logger.isTraceEnabled()) {                                logger.trace("Eagerly caching bean '" + beanName +                                                "' to allow for resolving potential circular references");                        }                        addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));                }                //...                Object exposedObject = bean;                try {                        // Bean属性填充                        populateBean(beanName, mbd, instanceWrapper);                        // 调用初始化方法,应用BeanPostProcessor后置处理器                        exposedObject = initializeBean(beanName, exposedObject, mbd);                }                //...                return exposedObject;        }

populateBean()中最后调用了applyPropertyValues(beanName, mbd, bw, pvs),applyPropertyValues(beanName, mbd, bw, pvs)方法中有调用了resolveValueIfNecessary(pv, originalValue),resolveValueIfNecessary(pv, originalValue)中又调用了resolveReference(argName, ref),好了终于到重要关头了,在resolveReference(argName, ref)中我们可用看到,又调用了getBean(refName)方法,获取beanB。呀,这是什么情况,怎么又回到起点了?哈哈,别着急,我们继续分析。 既然调用了getBean()方法,我们不妨在回头看看(代码我就不再贴一遍了)。 getBean()继续调用doGetBean()方法,然后继续调用getSingleton()方法去缓存中拿beanB,然后发现beanB也不再缓存中,然后就开始去创建beanB。创建beanB先进行实例化,然后放入到缓存中,之后再调用populateBean()进行属性填充(其实就是填充依赖beanA),之前我们提到beanA,在实例化beanB之前已经实例化完成并放入到三级缓存中了,这里我们就可以使用了,虽然还是个娃娃,但是够用了。到这里beanB属性填充之后就可以长大,成为完成的bean了。这时候将beanB放入到缓存池中,我们就可以回过头来填充beanA的属性了。到这里 ,beanA、beanB就完成了他们整个bean的创建过程了。

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {        //...        if (pvs != null) {                applyPropertyValues(beanName, mbd, bw, pvs);        }}protected void applyPropertyValues(String beanName, BeanDefinition mbd, BeanWrapper bw, PropertyValues pvs) {                //...                for (PropertyValue pv : original) {                        if (pv.isConverted()) {                                deepCopy.add(pv);                        } else {                                String propertyName = pv.getName();                                Object originalValue = pv.getValue();                                //                                Object resolvedValue = valueResolver.resolveValueIfNecessary(pv, originalValue);                                Object convertedValue = resolvedValue;                                //...                        }                }                //...        }public Object resolveValueIfNecessary(Object argName, @Nullable Object value) {                if (value instanceof RuntimeBeanReference) {                        RuntimeBeanReference ref = (RuntimeBeanReference) value;                        return resolveReference(argName, ref);                }                //...        }        private Object resolveReference(Object argName, RuntimeBeanReference ref) {                try {                        Object bean;                        String refName = ref.getBeanName();                        refName = String.valueOf(doEvaluate(refName));                        if (ref.isToParent()) {                                bean = this.beanFactory.getParentBeanFactory().getBean(refName);                        }                        else {                                bean = this.beanFactory.getBean(refName);                                this.beanFactory.registerDependentBean(refName, this.beanName);                        }                        if (bean instanceof NullBean) {                                bean = null;                        }                        return bean;                }                catch (BeansException ex) {}     

以上就是如何用spring源码剖析spring bean循环依赖,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注行业资讯频道。

方法 缓存 实例 循环 属性 处理 对象 源码 代码 分析 工作 处理器 容器 就是 接口 方式 表达式 准备 只是 情况 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 耶加雪菲 互联网最新的科技 互联网科技公司税收优惠 智能科技公司是互联网公司吗 腾讯阿里互联网科技 金融科技与互联网金融 互联网 科技创新 善班互联网科技有限公司 菲比寻常互联网科技 广西互联网科技公司 玖二柒互联网科技公司待遇 互联网企业和科技型企业 互联网科技创新的路径 互联网方面的科技前沿 互联网与数字科技关系 互联网科技包装股份有限公司上市 九思连强互联网电子科技有限公司 互联网企业和网络科技有限公司 现代科技的标志之一的互联网 知域互联网科技有限公司官网 互联网科技海报 互联网科技有限公司 翻译 金融科技与互联网金融相同和不同 湖南诚度互联网科技有限公司 江阴互联网智能科技产品进口 浙南科技城互联网大厦建设工程 东莞新华互联网科技学校 黑云互联网科技有限公司 重庆科技产业互联网有哪些 互联网企业和网络科技有限公司
0