欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-23 22:20:16
bean的注入方式有三种:注解方式注入,一般使用@Autowired、@Resource注解。构造器注入方式如下: setter方法注入...

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的加载流程图如下:

spring中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一起创建完毕。

本文地址:https://blog.csdn.net/qq_35261593/article/details/109966787

相关标签: java spring