Spring循环依赖

Spring循环依赖指的是类A依赖B,B又依赖A。这就依赖注入的时候会带来一定问题。下面说明一下,循环依赖的情况。

存在构造注入

public class AServieImpl implements AService{

    private TestService testService;

    public void setTestService(TestService testService){
        this.testService=testService;
    }

    public AServieImpl(){

    }

}
public class TestServiceImpl implements TestService {

    private AService aService;

    @Override
    public void test() {
        // TODO 自动生成的方法存根
        System.out.println("test serviceimpl");
    }

    public TestServiceImpl(AService aService){
        this.aService=aService;
    }
}
 <bean class="com.test.service.impl.AServiceImpl" name="aService" id="aService" >
        <property name="testService" ref="testService"></property>
     </bean>         
     <bean class="com.test.service.impl.TestServiceImpl" name="testService" id="testService" >
        <constructor-arg name="aService" ref="aService"></constructor-arg>
     </bean>

报错:
org.springframework.beans.factory.CannotLoadBeanClassException: Cannot find class [com.test.service.impl.AServiceImpl] for bean with name ‘aService’ defined in ServletContext resource [/WEB-INF/spring.xml];

构造注入是先初始化依赖对象,在实例化本身的。所以,当TestServiceImpl要实例化时,先初始化AService,然后去找AService。然而设值注入是先实例本身,在初始化依赖对象的。所以AService先实例化本身,同时要求依赖TestServiceImpl,然后并没有找到TestServiceImpl。所以报错。

Spring容器将每一个正在创建的bean标识符放在一个”当前创建bean池”中,bean标识符在创建过程中将一直保持在这个池中,因此如果在创建bean过程中发现自己已经在”当前创建bean池”里时,将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的bean将从”当前创建bean池”中清除掉。对于setter注入造成的依赖是通过Spring容器提前暴露刚完成无参构造函数实例化但未完成其他步骤(如setter注入)的bean来完成的,而且只能解决单例作用域的bean循环依赖。通过提前暴露一个单例工厂方法,从而使其他bean能引用到该bean:

addSingletonFactory(beanName, new ObjectFactory() {     
    public Object getObject() throws BeansException {     
        return getEarlyBeanReference(beanName, mbd, bean);     
    }     
}); 

单体的设值注入

public class AServieImpl implements AService{

    private TestService testService;

    public void setTestService(TestService testService){
        this.testService=testService;
    }

}
public class TestServiceImpl implements TestService {

    private AService aService;

    @Override
    public void test() {
        // TODO 自动生成的方法存根
        System.out.println("test serviceimpl");
    }

    public void setaService(AService aService) {
        this.aService = aService;
    }


}
<bean class="com.test.service.impl.AServieImpl" name="aService" id="aService" >
        <property name="testService" ref="testService"></property>
     </bean>         
     <bean class="com.test.service.impl.TestServiceImpl" name="testService" id="testService" >
        <property name="aService" ref="aService"></property>
     </bean>

单体的set注入是可以的。
但对于非单体就不行了。因为Spring容器不进行缓存”prototype”作用域的bean,因此无法提前暴露一个创建中的bean。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值