Spring循环依赖(源码上分析)

一、spring bean 的创建 四个阶段

1、实例化 instantiation(createBeanInstance)
2、属性赋值 Populate (populateBean)
3、初始化 Initialization(initializeBean)
4、销毁 Destruction(ConfigurableApplicationContext#close())

二、DefaultSingletonBeanRegistry 三个主要不同阶段bean的map

今天所要主要关注是 实例化 instantiation(createBeanInstance) 和
属性赋值 Populate (populateBean) 量阶段

在Spring的DefaultSingletonBeanRegistry类中,类上方挂着这三个Map:

1.singletonObjects:存放初始化好的bean
2.earlySingletonObjects:映射Bean的早期引用,也就是说在这个Map里的Bean不是完整的,
刚刚完成实例化 阶段的bean。

3.singletonFactories:映射创建Bean的原始工厂。

三、具体流程

1、先假设spring 初始化中有定义这两个类

@Component
public class A {
    @Autowired
    private B b;
}

@Component
public class B {
    @Autowired
    private A a;
}

2、假如先初始化A,我们从DefaultSingletonBeanRegistry ->getSingleton 作为入口进行分析

这里有参数需要特别关注:
isSingletonCurrentlyInCreation()判断当前单例bean是否正在创建中,也就是没有初始化完成(比如A的构造器依赖了B对象所以得先去创建B对象, 或则在A的populateBean过程中依赖了B对象,得先去创建B对象,这时的A就是处于创建中的状态。)
singletonsCurrentlyInCreation 这个set 是当前正在创建的bean的set集合

1、DefaultSingletonBeanRegistry ->getSingleton 中获取bean的时候
 public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        Map var3 = this.singletonObjects;
        synchronized(this.singletonObjects) {
        //当第一次中 实例化好map(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 (this.logger.isDebugEnabled()) {
                    this.logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
			
			//这个方法需要特别关注,这个方法里面会执行这行参数
			//this.singletonsCurrentlyInCreation.add(beanName) 这个添加到singletonsCurrentlyInCreation 会作为后面的重要判断
                this.beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = this.suppressedExceptions == null;
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet();
                }

                try {
                	//从这个方法中,会去创建bean
                    singletonObject = singletonFactory.getObject();
             
             。。。。。。。。(省略部分代码)
					//从中 singletonsCurrentlyInCreation 移除 beanName
                    this.afterSingletonCreation(beanName);
                }

                if (newSingleton) {
                // 在这个方法中将beanName 添加到singletonObjects,从singletonFactories 和 earlySingletonObjects 中移除。在此相当于完成了对beanName的初始化
                    this.addSingleton(beanName, singletonObject);
                }
            }

            return singletonObject;
        }
    }

2、在上一段代码 singletonFactory.getObject(); 会调用AbstractAutowireCapableBeanFactory 类 -> doCreateBean 方法
AbstractAutowireCapableBeanFactory 这个类是DefaultSingletonBeanRegistry 的子类

 protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
   。。。。(省略部分代码)
		//allowCircularReferences  和 isSingletonCurrentlyInCreation 都来自于父类的singletonFactory参数,
		//已经父类初始化和前面的方法改为true
        boolean earlySingletonExposure = mbd.isSingleton() && this.allowCircularReferences && this.isSingletonCurrentlyInCreation(beanName);
        if (earlySingletonExposure) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Eagerly caching bean '" + beanName + "' to allow for resolving potential circular references");
            }

		//这一步就是将beanName 放到singletonFactories 最开始的singletonFactories中
            this.addSingletonFactory(beanName, () -> {
                return this.getEarlyBeanReference(beanName, mbd, bean);
            });
        }

        Object exposedObject = bean;

        try {
          // 对实例化进行属性配置	
            this.populateBean(beanName, mbd, instanceWrapper);
            exposedObject = this.initializeBean(beanName, exposedObject, mbd);
        } catch (Throwable var18) {
            if (var18 instanceof BeanCreationException && beanName.equals(((BeanCreationException)var18).getBeanName())) {
                throw (BeanCreationException)var18;
            }
   。。。。(省略部分代码)

在上一段代码 populateBean(beanName, mbd, instanceWrapper);会调用AbstractAutowireCapableBeanFactory 类 -> populateBean 方法

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
     。。。。(省略部分代码)
            if (continueWithPropertyPopulation) {
                PropertyValues pvs = mbd.hasPropertyValues() ? mbd.getPropertyValues() : null;
                if (mbd.getResolvedAutowireMode() == 1 || mbd.getResolvedAutowireMode() == 2) {
                    MutablePropertyValues newPvs = new MutablePropertyValues((PropertyValues)pvs);
                    //1 为按名字注入
                    if (mbd.getResolvedAutowireMode() == 1) {
                        this.autowireByName(beanName, mbd, bw, newPvs);
                    }
				     //2 为按类型注入
                    if (mbd.getResolvedAutowireMode() == 2) {
                        this.autowireByType(beanName, mbd, bw, newPvs);
                    }

                    pvs = newPvs;
                }

                     。。。。(省略部分代码)

在上面的注入过程中由于A依赖B,同样进行上面的相同的操作,在通过B获取A的时候。
这个时候从singletonFactories移入earlySingletonObjects 中。此时B也获取到A第一次存在
singletonFactories 的中这个映射,A已经被注入B之中了。当B完成初始化,同样A继续完成
populateBean 方法,完成初始化。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
首先从singletonObjects获取是否存在以及初始化好的bean
    Object singletonObject = this.singletonObjects.get(beanName);
    如果没有,且依赖的A正在初始化,那我们去尝试看看earlySingletonObjects是否有对象
    earlySingletonObjects存放的是还未实例化好对象
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
    因为我们初始化bean都是加锁的,但是这边的锁对于循环依赖是没用的,因为我们都是实例化好对象
    准备设置属性的时候才发现循环依赖这个时候再去创建依赖对象,都是同一个线程此时锁是可重入的
        synchronized (this.singletonObjects) {
        从earlySingletonObjects获取
            singletonObject = this.earlySingletonObjects.get(beanName);
            获取不到 但是支持获取EarlyReference
            if (singletonObject == null && allowEarlyReference) {
            我们获取objectfactory,这个objectfactory就是
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
            中的() -> getEarlyBeanReference(beanName, mbd, bean),然后吧结果放入
            earlySingletonObjects,我们在整个单例创建结束的时候在把正在初始化好的对象放入
            singletonObjects,删除其他缓存中的对象,具体的可以看我们创建单例的时候 在方法结束时候会执行这个操作
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    singletonObject = singletonFactory.getObject();
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject;
}

如果话总结一下就是,对象A实例化之后都放到一个暂存区,然后继续进行属性配置。当A的成员B同样依赖A的时候,B可以直接从暂存区取到处于实例化状态的A 完成B的初始化。A再用B完成A的初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值