• Spring Boot源码(七):循环依赖


    循环依赖

    以及

    spring是如何解决循环依赖的

    循环依赖

    通俗来说

    就是beanA中依赖了beanB,beanB中也依赖了beanA。

    spring是支持循环依赖的,但是默认只支持单例的循环依赖,如果bean中依赖了原型bean,则需要加上lookup方法。

    继续之前的项目,改造了People,User类:

    @Component
    public class People {
        @Autowired
        private User user;
        public People(){
            System.out.println("create People");
        }
    }
    @Component
    public class User {
        @Autowired
        private People people;
        public User(){
            System.out.println("create User");
        }
    }

    People--(依赖)-->User--(依赖)-->People--(依赖)-->User.......,这就形成了循环依赖。

    继续进入上篇的preInstantiateSingletons()方法:

     进行条件断点:

     

     进入上篇说的getSingleTon()方法:

     singletonObjects是spring的单例池,从其中没有拿到bean,singletonObject为null,且isSingletonCurrentlyInCreation()为false。

    public boolean isSingletonCurrentlyInCreation(String beanName) {
            return this.singletonsCurrentlyInCreation.contains(beanName);
        }

    其实这个方法就是去判断该map(singletonCurrentlyInCreation)是否包含该bean?(这里是people)。

    这个方法通俗意思就是 “该bean是否在创建过程中?”

    先不管这个意思,继续往下走。

    spring创建对象前还会做很多判断,例如是否为原型,是否抽象?

     这里的getSingleton(String beanName, ObjectFactory<?> singletonFactory)是重载,与之前的getSingleton(String beanName, boolean allowEarlyReference)不同。

    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 + "'");
                    }
                    beforeSingletonCreation(beanName);
                    boolean newSingleton = false;
                    boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = new LinkedHashSet<>();
                    }
                    try {
                        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;
            }
        }

    protected void beforeSingletonCreation(String beanName) {
            if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
        }

    此方法把 “people”放入singletonsCurrentlyInCreation中,那么isSingletonCurrentlyInCreation("people")这时为true

    进入lambda表达式 createBean()

    create People Object ----注入依赖发现依赖User--->create User Object---发现依赖People---create People Object---发现isSingletonCurrentlyInCreation(beanName)为true,表示正在创建People:

     然后才会执行里面的代码:

     allowEarlyReference 是否允许从singletonFactories中通过getObject拿到对象,也就是执行if中的方法。

    我们看一下singletonObjects(一级缓存),earlySingletonObjects(二级缓存),singletonFactories(三级缓存)。

    AbstractAutowireCapableBeanFactory#doCreateBean()中:

     

     这时候存进去的并不是完整的bean:

     但是可以供User依赖注入了,这也就是spring对循环依赖的解决。

  • 相关阅读:
    java实现趣味拼算式
    windows下安装docker
    Docker_入门?只要这篇就够了!(纯干货适合0基础小白)
    网关支付、银联代扣通道、快捷支付、银行卡支付分别是怎么样进行支付的?
    【深度解析】第三方支付的分类、接口与支付流程
    去外包公司的伙伴们小心了!——亲身经历,数数外包公司的坑
    一个tomcat下部署多个项目或一个服务器部署多个tomcat
    tomcat部署web应用的4种方法以及部署多个应用
    datatables增删改查的实现
    基于SpringMVC+Bootstrap+DataTables实现表格服务端分页、模糊查询
  • 原文地址:https://www.cnblogs.com/SunSAS/p/12308138.html
Copyright © 2020-2023  润新知