Spring 循环依赖

循环依赖:如果使用构造函数注入,则可能创建无法解决的循环依赖,所以尽量使用构造set方法注入。

1.构造函数

@Component
public class ServiceA {

    private ServiceB serviceB;

    public ServiceA(ServiceB serviceB) {
        this.serviceB = serviceB;
    }
}
@Component
public class ServiceB {
    private ServiceA serviceA;

    public ServiceB(ServiceA serviceA) {
        this.serviceA = serviceA;
    }
}
public static void main(String[] args) throws InterruptedException{
        new ServiceA(new ServiceB(new ServiceA(......)))    // 一直new下去
    }

2.set方法

public class ServiceAA {
    private ServiceBB serviceBB;

    public void setServiceBB(ServiceBB serviceBB) {
        this.serviceBB = serviceBB;
        System.out.println("A 里面设置了B");
    }
}
public class ServiceBB {
    private ServiceAA serviceAA;

    public void setServiceAA(ServiceAA serviceAA) {
        this.serviceAA = serviceAA;
        System.out.println("B 里面设置了A");
    }
}
public static void main(String[] args) throws InterruptedException{
        //new ServiceA(new ServiceB(new ServiceA()))
        ServiceAA a = new ServiceAA();
        ServiceBB b = new ServiceBB();
        b.setServiceAA(a);
        a.setServiceBB(b);
    }

3.使用Spring容器创建

public class A {
    private B b;

    public B getB() {
        return b;
    }

    public void setB(B b) {
        this.b = b;
    }

    public A() {
        System.out.println("---A created success");
    }
}
public class B {
    private A a;

    public A getA() {
        return a;
    }

    public void setA(A a) {
        this.a = a;
    }

    public B() {
        System.out.println("---B created success");
    }
}
public class ClientSpringContainer {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        A a = context.getBean("a", A.class);
        B b = context.getBean("b", B.class);
    }
}

 scope="singleton"不会产生循环依赖

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">



    <bean id="b" class="com.atguigu.study.spring.circulardepend.B" scope="singleton">
        <property name="a" ref="a"/>
    </bean>
    <bean id="a" class="com.atguigu.study.spring.circulardepend.A" scope="singleton">
        <property name="b" ref="b"/>
    </bean>


</beans>

 scope="prototype"会产生循环依赖,报错部分信息如下:

......:Is there an unresolvable circular reference?

 4.Spring怎么解决循环依赖的

public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
    protected final Log logger = LogFactory.getLog(this.getClass());
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap(256);
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap(16);
    private final Map<String, Object> earlySingletonObjects = new HashMap(16);
    private final Set<String> registeredSingletons = new LinkedHashSet(256);
    private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap(16));
    private final Set<String> inCreationCheckExclusions = Collections.newSetFromMap(new ConcurrentHashMap(16));

在DefaultSingletonBeanRegistry 类中使用三个不同的Map,分别是singletonObjects是一级缓存,earlySingletonObjects是二级缓存,singletonFactories是三级缓存。

只有单例bean会通过三级缓存提前暴露来解决循环依赖的问题,而非单例的bean,每次从容器中获取都是一个新的对象,都会重新创建,所以非单例bean是没有缓存的,不会将其放在三级缓存中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值