• 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对循环依赖的解决。

  • 相关阅读:
    js项目结合的注意点
    cookie练习
    json记载字符个数
    js,jQuery获取标签
    新人签到
    使用Resources类搭建Unity简单的资源管理工具类
    初识vue
    原生JS写出贪吃蛇
    用js做一个简单的班级点名器
    Javascript 的"循环语句"
  • 原文地址:https://www.cnblogs.com/SunSAS/p/12308138.html
Copyright © 2020-2023  润新知