spring中bean的注入方式 & 循环依赖

bean的注入方式有三种:

 1.  注解方式注入,一般使用@Autowired、@Resource注解。
 2.  构造器注入方式如下:
配置文件:
	<bean id="a" class="org.example.constructor.A">
	   <constructor-arg ref="b"/>
	</bean>
	<bean id="b" class="org.example.constructor.B"/>
实体bean:
	public class A {
	
	    public A(B b) {
	    }
	}
3. setter方法注入如下:
配置文件:
	<bean id="person" class="org.example.CircularReferences.bean.Person" scope="prototype">
	        <property name="customer" ref="customer"></property>
	 </bean>
实体bean:
	public class Customer {
	
	    public Person person;
	
	    public void setPerson(Person person) {
	        this.person = person;
	    }
	}

spring是如何解决bean循环依赖(相互依赖)的,我们来分析核心源码:

核心容器类DefaultSingletonBeanRegistry,里面有几个比较重要的属性变量,需要着重说明一下:
1. singletonObjects 单例对象列表, beanName -> bean实例
2. singletonFactories 单例工厂列表 beanName -> beanFactory
3. earlySingletonObjects 循环对象依赖列表,对象在创建之后,进行注入过程中,发现产生了循环依赖,那么会将对象放入到这个队列,并且从singletonFactories中移除掉。
4. singletonsCurrentlyInCreation 正在创建的单例名称队列
5. registeredSingletons 已经创建成功的单例名称列表

spring只能解决上面第一种或第三种方式的循环依赖,且要求单例的bean,不能解决构造器的循环依赖。
这里举例有两个bean,A和B,循环依赖bean的加载流程图如下:

在这里插入图片描述

跟踪bean的创建流程进入AbstractAutowireCapableBeanFactory类的doCreateBean()方法,核心代码:
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
            throws BeanCreationException {

        BeanWrapper instanceWrapper = null;
        // 省略代码
        if (instanceWrapper == null) {
            // 实例化bean
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
			
		//判断是单例、允许循环依赖、正在创建的单例队列bean
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        //提早暴露
        if (earlySingletonExposure) {
            // 重点!!!将实例化的对象添加到singletonFactories三级缓存中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }
        // 初始化bean
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);//也很重要
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }
        // 省略无关代码
        return exposedObject;
}
拿自动注入来说,当bean A走到populateBean()方法时,会调用到AutowiredAnnotationBeanPostProcessor类中的postProcessProperties()方法,最后会调用到beanFactory.getBean(beanName)。然后bean B会被创建,bean B创建时从singletonFactories缓存中拿到A作为自己的属性依赖,然后将B赋值给A,最后A、B一起创建完毕。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值