Java 程序员程序员Java

Spring高频面试题:如何解决循环依赖问题

2020-11-17  本文已影响0人  马小莫QAQ

循环依赖问题全景图

什么是循环依赖问题?

类与类之间的依赖关系形成了闭环,就会导致循环依赖问题的产生。

比如下图中A类依赖了B类,B类依赖了C类,而最后C类又依赖了A类,这样就形成了循环依赖问题。

循环依赖问题案例分析

public class ClassA {
    private ClassB classB;

    public ClassB getClassB() {
        return classB;
    }

    public void setClassB(ClassB classB) {
        this.classB = classB;
    }
}
public class ClassB {
    private ClassA classA;

    public ClassA getClassA() {
        return classA;
    }

    public void setClassA(ClassA classA) {
        this.classA = classA;
    }
}
<?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
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="classA" class="ioc.cd.ClassA">
        <property name="classB" ref="classB"></property>
    </bean>
    <bean id="classB" class="ioc.cd.ClassB">
        <property name="classA" ref="classA"></property>
    </bean>
</beans>
    @Test
    public void test() throws Exception {
        // 创建IoC容器,并进行初始化
        String resource = "spring/spring-ioc-circular-dependency.xml";
        ApplicationContext context = new ClassPathXmlApplicationContext(resource);
        // 获取ClassA的实例(此时会发生循环依赖)
        ClassA classA = (ClassA) context.getBean(ClassA.class);
    }

以上案例有几种循环依赖问题?

循环依赖问题在Spring中主要有三种情况:

注意:在Spring中,只有【第三种方式】的循环依赖问题被解决了,其他两种方式在遇到循环依赖问题时都会产生异常。

其实也很好解释:

如何解决循环依赖问题?

那Spring到底是如何解决的setter方法依赖注入引起的循环依赖问题呢?请看下图(其实主要是通过两个缓存来解决的):

Spring三大缓存介绍

Spring中有三个缓存,用于存储单例的Bean实例,这三个缓存是彼此互斥的,不会针对同一个Bean的实例同时存储。

如果调用getBean,则需要从三个缓存中依次获取指定的Bean实例。 读取顺序依次是一级缓存-->二级缓存-->三级缓存

一级缓存:Map<String, Object> singletonObjects

第一级缓存的作用?

存储什么数据?

第二级缓存:Map<String, Object> earlySingletonObjects

第二级缓存的作用?

存储什么数据?

第三级缓存:Map<String, ObjectFactory<?>> singletonFactories

第三级缓存的作用?

存储什么数据?

为什么第三级缓存要使用ObjectFactory?需要提前产生代理对象。

什么时候将Bean的引用提前暴露给第三级缓存的ObjectFactory持有?时机就是在第一步实例化之后,第二步依赖注入之前,完成此操作。

总结

以上就是Spring解决循环依赖的关键点!总结来说,就是要搞清楚以下几点:

作者:IT护道师_灭霸詹
链接:https://juejin.im/post/6895753832815394824
来源:掘金

上一篇下一篇

猜你喜欢

热点阅读