Spring Bean 循环依赖

创建 A 实例时需要 B,创建 B实例时需要 A。

测试环境:https://gitee.com/jhxxb/MySpringBoot/tree/master/Spring-Base/src/test/java/BeanCircularDependency

Spring IOC 中 Bean 的作用域有多种:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes

默认 Bean 作用域为单例模式,Spring 解决循环依赖只能解决单例模式下的,无法解决多实例循环依赖,因为每次都需要 new,无法使用缓存

单例模式下也无法解决构造器方式注入的循环依赖,必须要有一个 Bean 不是构造器注入

总的来说 Spring 只能解决单例模式下的非构造器注入的循环依赖问题

注:Spring Boot 2.6.0 开始循环引用默认是被禁用的(只是 Spring Boot 默认禁止了,Spring Framework 默认还是允许)

可以配置开启
spring.main.allow-circular-references=true

前置知识

先清楚 Spring 中的两个概念

  • 实例化:就是 new 一个对象
  • 初始化:给 new 的对象设置属性

还需要了解下 Spring IOC 中的三级缓存,平常所说的 IOC 容器就是一个 ConcurrentHashMap

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    /**
     * 一级缓存,单例对象的缓存:bean名称-bean实例,存放生成好的单例 Bean
     */
    private final Map singletonObjects = new ConcurrentHashMap<>(256);

    /**
     * 三级缓存,单例工厂的缓存:bean名称-ObjectFactory,存放生成 bean 的工厂
     */
    private final Map> singletonFactories = new HashMap<>(16);

    /**
     * 二级缓存,早期的单例对象的缓存:bean名称-bean实例,存放实例化但未初始化(Bean 的属性还未填充)的单例 bean
     */
    private final Map earlySingletonObjects = new ConcurrentHashMap<>(16);

过程,分三步

  1. A 创建过程中需要 B,于是 A 将自己放到三级缓里面,去实例化 B
  2. B 实例化的时候发现需要 A,于是 B 先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了 A,然后把三级缓存里面的这个 A 放到二级缓存里面,并删除三级缓存里面的 A
  3. B 顺利初始化完毕,将自己放到一级缓存里面(此时 B 里面的 A 依然是创建中状态),然后回来接着创建 A,此时 B 已经创建结束,A 直接从一级缓存里面拿到 B,然后 A 完成创建,并将 A 自己放到一级缓存里面。

源码(已删除部分影响阅读的代码,主要看处理流程)

从获取对象开始,开始创建 A 对象,其实就是 IOC 的初始化流程:https://www.cnblogs.com/jhxxb/p/13609289.html

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Override
    public void preInstantiateSingletons() throws BeansException {
        List beanNames = new ArrayList<>(this.beanDefinitionNames);
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) { // 是否为工厂 Bean
                } else {
                    getBean(beanName); // 获取 Bean 对象
                }
            }
        }

进入到 getBean(beanName) 获取 Bean

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    @SuppressWarnings("unchecked")
    protected  T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) {
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else { // 没有获取到 A 对象,会进入到这里
            if (isPrototypeCurrentlyInCreation(beanName)) { // 检查正在创建中的 Bean 是否包含 A,如果是那就抛异常(循环依赖)
                throw new BeanCurrentlyInCreationException(beanName);
            }
            try {// 是否有 Bean 需要在 A 之前创建
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                }

                if (mbd.isSingleton()) { // 创建单例模式 Bean
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        } catch (BeansException ex) {
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) { // 创建原型模式 Bean
                } else { // 其它 scope 类型的处理
                }
            }
        }

        return adaptBeanInstance(name, beanInstance, requiredType);
    }

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    @Override
    @Nullable
    public Object getSingleton(String beanName) { // 去容器中拿 Bean,有则直接返回
        return getSingleton(beanName, true);
    }

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName); // 获取单例 Bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 是否正在创建中
        }
        return singletonObject; // A 没有创建过,直接到这里
    }

    public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                beforeSingletonCreation(beanName); // singletonsCurrentlyInCreation 把它添加进去,证明这个 Bean 正在创建中
                boolean newSingleton = false;
                try {
                    singletonObject = singletonFactory.getObject(); // 创建 Bean
                    newSingleton = true;
                } catch (IllegalStateException ex) {
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                } finally {
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

进入到 createBean(beanName, mbd, args) 开始创建 Bean

public abstract class AbstractAutowireCapableBeanFactory extends org.springframework.beans.factory.support.AbstractBeanFactory implements AutowireCapableBeanFactory {
    @Override
    protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        try {
            // 给 Bean 一个返回代理对象的机会
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }

        try {
            Object beanInstance = doCreateBean(beanName, mbdToUse, args); // 创建 Bean
            return beanInstance;
        }
    }

    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        if (instanceWrapper == null) {
            instanceWrapper = createBeanInstance(beanName, mbd, args); // 创建 Bean 实例
        }

        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) { // 放入三级缓存
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        try {
            populateBean(beanName, mbd, instanceWrapper); // 属性填充,其中会实例化 B
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }

        return exposedObject;
    }

    @SuppressWarnings("deprecation")
    protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
        if (hasInstAwareBpps) {
            for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
                PropertyValues pvsToUse = bp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                if (pvsToUse == null) {
                    // 关于 postProcessPropertyValues 的实现,有几个处理器是非常关键的:
                    // 如 AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor 等
                    pvsToUse = bp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {
                        return;
                    }
                }
                pvs = pvsToUse;
            }
        }
    }
}

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware {
    @Deprecated
    @Override
    public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) {
        return postProcessProperties(pvs, bean, beanName);
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
        InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
        try {
            metadata.inject(bean, beanName, pvs);
        }
        return pvs;
    }

    private class AutowiredFieldElement extends InjectedElement {
        @Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            if (this.cached) {
                value = resolvedCachedArgument(beanName, this.cachedFieldValue);
            } else {
                try {
                    value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter); // 获取 B 对象
                }
            }
            if (value != null) {
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value); // 设置实例对象 A 的属性 B
            }
        }
    }
}

public class InjectionMetadata {
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection checkedElements = this.checkedElements;
        Collection elementsToIterate = (checkedElements != null ? checkedElements : this.injectedElements);
        if (!elementsToIterate.isEmpty()) {
            for (InjectedElement element : elementsToIterate) {
                element.inject(target, beanName, pvs); // AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement#inject
            }
        }
    }
}

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        if (Optional.class == descriptor.getDependencyType()) {
        } else if (ObjectFactory.class == descriptor.getDependencyType() || ObjectProvider.class == descriptor.getDependencyType()) {
        } else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
        } else {
            Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(descriptor, requestingBeanName);
            if (result == null) {
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter); // 解析依赖 B
            }
            return result;
        }
    }

    @Nullable
    public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName, @Nullable Set autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {
        try {
            Object shortcut = descriptor.resolveShortcut(this);
            if (shortcut != null) {
                return shortcut;
            }

            if (instanceCandidate instanceof Class) {
                instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this); // 获取依赖的实例对象
            }
            Object result = instanceCandidate;
            return result;
        }
    }
}

public class DependencyDescriptor extends InjectionPoint implements Serializable {
    public Object resolveCandidate(String beanName, Class requiredType, BeanFactory beanFactory) throws BeansException {
        return beanFactory.getBean(beanName); // 又回到了 getBean 方法获取实例 B
    }
}

创建 B 实例时同样会走到 DependencyDescriptor#resolveCandidate 来又创建 A,看 Spring 是怎么处理的

public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }

    @SuppressWarnings("unchecked")
    protected  T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
        String beanName = transformedBeanName(name);
        Object beanInstance;

        Object sharedInstance = getSingleton(beanName);
        if (sharedInstance != null && args == null) { // 可以获取到 A 对象
            beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
        }

        return adaptBeanInstance(name, beanInstance, requiredType);
    }

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    @Override
    @Nullable
    public Object getSingleton(String beanName) { // 去容器中拿 Bean,有则直接返回
        return getSingleton(beanName, true);
    }

    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        Object singletonObject = this.singletonObjects.get(beanName); // 从一级缓存中获取单例 Bean
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) { // 是否正在创建中
            // 会进入到这里,A 确实是正在创建中
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                synchronized (this.singletonObjects) {
                    singletonObject = this.singletonObjects.get(beanName); // 再次从一级缓存中获取
                    if (singletonObject == null) {
                        singletonObject = this.earlySingletonObjects.get(beanName); // 从二级缓存中获取
                        if (singletonObject == null) {
                            ObjectFactory singletonFactory = this.singletonFactories.get(beanName); // 从三级缓存中获取,显然可以获取到
                            if (singletonFactory != null) {
                                singletonObject = singletonFactory.getObject(); // 获取未赋属性值的 A 对象
                                this.earlySingletonObjects.put(beanName, singletonObject); // 将 A 加入到二级缓存
                                this.singletonFactories.remove(beanName); // 把 A 从三级缓存中移除
                            }
                        }
                    }
                }
            }
        }
        return singletonObject; // 返回未赋属性值的 A 对象
    }

继续看 B 对象的创建,它会在 A 对象之前创建出来

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
        synchronized (this.singletonObjects) {
            Object singletonObject = this.singletonObjects.get(beanName);
            if (singletonObject == null) {
                beforeSingletonCreation(beanName); // singletonsCurrentlyInCreation 把它添加进去,证明这个 Bean 正在创建中
                boolean newSingleton = false;
                try {
                    singletonObject = singletonFactory.getObject(); // 创建 B 对象完成
                    newSingleton = true;
                } finally {
                    afterSingletonCreation(beanName); // 从 singletonsCurrentlyInCreation 中移除
                }
                // 若是新创建的 Bean,那就执行 addSingleton 方法
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

    protected void addSingleton(String beanName, Object singletonObject) { // Bean 彻底创建完成,添加进 singletonObjects
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject); // 把实例 B 放入一级缓存,B 直接从三级缓存到了一级缓存
            this.singletonFactories.remove(beanName); // 从三级缓存中删除
            this.earlySingletonObjects.remove(beanName); // 从二级缓存中删除
            this.registeredSingletons.add(beanName); // 记录已经创建好的 Bean 的名称,有顺序
        }
    }

之后 A 会像 B 一样被创建出来。

回到最开始,A 创建完后会继续创建 B,但这时就不会再走创建流程了,直接可以获取到 B

public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Override
    public void preInstantiateSingletons() throws BeansException {
        List beanNames = new ArrayList<>(this.beanDefinitionNames);
        for (String beanName : beanNames) {
            RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
            if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
                if (isFactoryBean(beanName)) { // 是否为工厂 Bean
                } else {
                    getBean(beanName); // 可以直接获取到 B 对象,没有了后续的创建流程
                }
            }
        }

Spring 中加入三级缓存的代码

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
    }

    protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { // 从创建工厂中获取实例对象,会对 Bean 进行一些处理
        Object exposedObject = bean;
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
                exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
            }
        }
        return exposedObject;
    }

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    protected void addSingletonFactory(String beanName, ObjectFactory singletonFactory) {
        synchronized (this.singletonObjects) {
            if (!this.singletonObjects.containsKey(beanName)) {
                this.singletonFactories.put(beanName, singletonFactory); // 加入三级缓存,是创建工厂,并非实例对象
                this.earlySingletonObjects.remove(beanName);
                this.registeredSingletons.add(beanName);
            }
        }
    }

图示

Spring Bean 循环依赖

关闭 Spring 的循环依赖

查看源码可以发现有一个 allowCircularReferences 属性可以控制

public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory implements AutowireCapableBeanFactory {
    /** Whether to automatically try to resolve circular references between beans. */
    private boolean allowCircularReferences = true;

https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#beans-dependency-resolution

https://blog.csdn.net/f641385712/article/details/92801300

Original: https://www.cnblogs.com/jhxxb/p/14421578.html
Author: 江湖小小白
Title: Spring Bean 循环依赖

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/540329/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • JavaPersistenceWithMyBatis3笔记-第5章Configuring MyBatis in a Spring applications-001

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年5月29日
    085
  • 永辉彩食鲜架构概述

    背景 满足整个大B业务从线上到供应链的全线业务系统的研发和维护,保证整个系统的稳定性和性能。 架构思考 大B业务不同于小B业务,它没有常见的业务高并发的场景,所以更多是对业务数据的…

    Java 2023年6月8日
    0102
  • Dijkstra算法(三)之 Java详解

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。 基本…

    Java 2023年5月29日
    079
  • 浅谈JAVARMI

    浅谈JAVA-RMI serverdemo: package com.ray.rmi; import java.rmi.Naming; import java.rmi.Remote…

    Java 2023年6月6日
    065
  • Windows安装jdk1.8和配置环境变量

    Original: https://www.cnblogs.com/qtiger/p/15986266.htmlAuthor: 搬砖滴Title: Windows安装jdk1.8和…

    Java 2023年5月30日
    075
  • 【每天学一点-03】 使用Html5+Less实现简单的静态登录界面(入门Less)

    1、首先引用Less 有npm安装、cdn引用、或者下载Less.js本地引用,我采用的是第三种方法 less.js引用: 下载地址:https://github.com/less…

    Java 2023年6月5日
    091
  • dubbo源码分析3(dubbo中的spi机制)

    上一篇我们看过了jdk中的spi机制,也分析了它的缺点就是会一次性将META-INF/services下的配置文件中,对应接口的全部实现类都给加载; 而dubbo中的spi肯定是提…

    Java 2023年6月6日
    084
  • java并发体系

    posted @2022-02-17 11:37 雄狮_杜 阅读(11 ) 评论() 编辑 Original: https://www.cnblogs.com/duyinqiang…

    Java 2023年5月29日
    088
  • 70.刺

    dsfsd posted @2022-09-28 08:47 随遇而安== 阅读(7 ) 评论() 编辑 Original: https://www.cnblogs.com/55z…

    Java 2023年6月7日
    074
  • 【年度钻石】Linux云计算+运维笔记(2)《博学谷-黑马》

    防火墙分类 【年度钻石】Linux云计算+运维笔记(2)《博学谷-黑马》 逻辑上划分,防火墙可以大体分为主机防火墙和网络防火墙主机防火墙:针对于单个主机进行防护网络防火墙:针对网络…

    Java 2023年6月7日
    084
  • Java内部类初探

    Java内部类初探 之前对内部类的概念不太清晰,在此对内部类与外部类之间的关系以及它们之间的调用方式进行一个总结。 Java内部类一般可以分为以下三种: 成员内部类 静态内部类 匿…

    Java 2023年6月8日
    086
  • 基于LSM的Key-Value数据库实现初篇

    前篇文章对LSM的基本原理,算法流程做了简单的介绍,这篇文章将实现一个简单的 基于LSM算法的 迷你Key-Value数据库,结合上篇文章的理论与本篇文章的实践使之对LSM算法有更…

    Java 2023年6月16日
    094
  • RabbitMQ

    异步处理 应用解耦 流量控制、削峰 1)消息中间件有两个重要的概念:消息代理和目的地 当消息发送者发送消息后,将由消息代理接管,消息代理保证消息传递到指定目的地 2)消息队列主要有…

    Java 2023年5月30日
    0107
  • spring IOC的理解,原理与底层实现?

    从总体到局部 控制反转:理论思想,原来的对象是由使用者来进行控制,有了spring之后,可以把整个对象交给spring来帮我们进行管理DI(依赖注入):把对应的属性的值注入到具体的…

    Java 2023年6月8日
    076
  • [javaweb]jsp,jstl,el表达式的使用

    jsp java server page:java服务器前端页面,和servlet一样,用于动态web开发。 特点: 写jsp页面就像在写html html只给用户提供静态数据,j…

    Java 2023年6月6日
    095
  • CAS原子性操作

    CAS原理解析 1、CAS基本概念 CAS(Compare And Swap)也叫做比较与交换,是一种无锁原子算法,映射到操作系统就是一条cmpxchg硬件汇编指令,通过硬件命令保…

    Java 2023年6月5日
    079
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球