Qouson's blog Qouson's blog
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

qouson

Java界的小学生
首页
  • Java 基础

    • 基础
    • String
  • Java 中级

    • 网络编程
  • Java 高级

    • JVM
    • 多线程
  • Spring
  • SpringMVC
  • SpringBoot
  • MySQL
  • Redis
  • MQ
  • ZooKeeper
  • git
  • linux
  • 设计模式
  • 数据结构与算法
  • 计算机基础
  • Java相关框架
  • 分布式
  • DDD领域驱动设计
  • 系统设计
  • 杂乱无章
Java知识图谱
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Spring

    • Spring
    • AOP

    • IOC

      • Spring-IOC
        • 循环依赖
  • SpringMVC

  • SpringBoot

  • SpringCloud

  • Spring
  • Spring
  • IOC
qouson
2024-05-23
目录

Spring-IOC

# Spring-IOC

# 循环依赖

  • 面试题
    • 解释一下Spring中的三级缓存
    • 三级缓存是什么?三个Map有什么异同
    • 什么是循环依赖?请你谈谈?看过Spring源码吗?一般说的Spring容器是什么?
    • 如何检测是否存在循环依赖?实际开发中见过循环依赖的异常吗?
    • 多例情况下,循环依赖问题为什么无法解决?
  • 什么是循环依赖?
    • 多个bean之间互相依赖,形成了一个闭环。比如,A依赖于B,B依赖于C,C依赖于A。(或AB互相依赖) 20210320233354
    • 通常来说,如果问Spring是如何解决循环依赖的问题的,一定是指默认的单例Bean中,属性互相引用的场景。注:定义bean的时候,可以指定scope为singleton/prototype
  • 两种注入方式对循环依赖的影响
    • 循环依赖官网说明 20210320233619
    • 结论
      • 只要bean的注入方式是setter且singleton的就不会有循环依赖问题,Spring用三级缓存解决了。DefaultSingletonBeanRegistry 20210321100106
  • Spring容器循环依赖报错演示BeanCurrentlyInCreationException
    • 在Spring容器中注入依赖的对象有两种方式

      • constructor
        • code

          @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 class ClientConstructor {
              public static void main(String[] args) {
                  //俄罗斯套娃,无穷无尽
                  new ServiceA(new ServiceB(new ServiceA(new ServiceB())));
              }
          }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
        • 结论

          • 构造器循环依赖是无法解决的
      • setter
        • code

          @Component
          public class ServiceA {
              private ServiceB serviceB;
              public void setServiceB(ServiceB serviceB){
                  this.serviceB = serviceB;
              }
          }
          @Component
          public class ServiceB {
              private ServiceA serviceA;
              public void setServiceA(ServiceA serviceA){
                  this.serviceA = serviceA;
              }
          }
          public class ClientSetter {
              public static void main(String[] args) {
                  //成功注入
                  ServiceA serviceA = new ServiceA();
                  ServiceB serviceB = new ServiceB();
                  serviceA.setServiceB(serviceB);
                  serviceB.setServiceA(serviceA);
              }
          }
          
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          13
          14
          15
          16
          17
          18
          19
          20
          21
          22
          23
    • Spring IOC Case

      • 默认单例(singleton)的场景是支持循环依赖的,不会报错

        • applicationContext.xml
        <?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
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd
              http://www.springframework.org/schema/tx
              http://www.springframework.org/schema/tx/spring-tx.xsd">
              <bean id="a" class="com.jjc.mypratice.spring.ioc.circulardepend.A">
                  <property name="b" ref="b"/>
              </bean>
              <bean id="b" class="com.jjc.mypratice.spring.ioc.circulardepend.B">
                  <property name="a" ref="a"/>
              </bean>
        </beans>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        • bean
        public class CircularDependBugTest {
            public static void main(String[] args) {
                ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
                A a = applicationContext.getBean("a", A.class);
                B b = applicationContext.getBean("b", B.class);
            }
        }
          
        
        1
        2
        3
        4
        5
        6
        7
        8
        • 执行结果 20210321000757
      • 原型(prototype)的场景是不支持循环依赖的,会报错

        • applicationContext.xml
        <?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
              http://www.springframework.org/schema/context
              http://www.springframework.org/schema/context/spring-context.xsd
              http://www.springframework.org/schema/aop
              http://www.springframework.org/schema/aop/spring-aop.xsd
              http://www.springframework.org/schema/tx
              http://www.springframework.org/schema/tx/spring-tx.xsd">
              <bean id="a" class="com.jjc.mypratice.spring.ioc.circulardepend.A" scope="prototype">
                  <property name="b" ref="b"/>
              </bean>
              <bean id="b" class="com.jjc.mypratice.spring.ioc.circulardepend.B" scope="prototype">
                  <property name="a" ref="a"/>
              </bean>
        </beans>
        
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        • bean
        public class CircularDependBugTest {
            public static void main(String[] args) {
                ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
                A a = applicationContext.getBean("a", A.class);
                B b = applicationContext.getBean("b", B.class);
            }
        }
          
        
        1
        2
        3
        4
        5
        6
        7
        8
        • 执行结果 20210321000942
    • 结论

      • singleton可以解决循环依赖
  • 循环依赖debug
    • 实例化/初始化
      • 实例化create
        • 内存中开辟一块空间
        • 类比,租赁/买好房子,还没置办家具/装修
      • 初始化populate
        • 完成属性的赋值
        • 类比,置办家具/装修
    • 3个Map和4个方法 20210321001825
    • A/B对象在三级缓存中的迁移
    • Debug 20210321001722
  • 总结----Spring是如何解决循环依赖的
    • 如何解决 20210321001949 20210321002021 20210321002041
    • 流程 20210321002131 Spring-IOC-circular-dependence
编辑 (opens new window)
上次更新: 2024/05/24, 11:36:46
Spring-AOP
springMVC

← Spring-AOP springMVC→

最近更新
01
杂乱无章
12-25
02
基础-大彬
11-14
03
集合-大彬
11-14
更多文章>
Theme by Vdoing | Copyright © 2023-2025 qouson
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式