暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Spring 中的循环依赖

程序员舒克 2021-12-31
127

01

什么是循环依赖

循环依赖就是循环引用,就是两个或多个Bean相互之间的持有对方,比如ClassA引用ClassB,ClassB引用ClassA,则它们最终反映为一个环。如下图!

02
有哪几种循依赖

Spring容器循环依赖包括构造器循环依赖setter循环依赖

构造器循环依赖(代码如下)_________
定义《01:什么是循环依赖》里所说的两个类
    // 定义ClassA类
    public class ClassA {


    private ClassB classB;


    public ClassA(ClassB classB) {
    this.classB = classB;
    }
    }

      //定义ClassB类
      public class ClassB {


      private ClassA classA;


      public ClassB(ClassA classA) {
      this.classA = classA;
      }
      }
      将ClassA、ClassB注入到Spring容器中(代码如下)
        @Configuration
        public class Config {


        @Bean
        public ClassA classA(ClassB classB){
        return new ClassA(classB);
        }


        @Bean
        public ClassB classB(ClassA classA){
        return new ClassB(classA);
        }
        }


        测试、看控制台报错提醒

          public class Test {
          public static void main(String[] args) {
          AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
          }
          }
          注:AnnotationConfigApplicationContext 用来读取配置类信息,读取到配置之后,就可以从Spring容器中获取我们注入的bean。当然,在平时写业务时,我们都习惯了用Junit测试类,测试Service或者Mapper等方法,如果bean是通过配置类注入的,或者通过xml注入的,也可以尝试用main方法测试,根据各自喜好,总之好几种方法都可以实现(题外话,扯远了)
          查看控制台日志

          Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'classA': Requested bean is currently in creation: Is there an unresolvable circular reference?


          • 创建名为“classA”的 bean 时出错:当前正在创建请求的 bean:是否存在无法解析的循环引用?


          构造器循环依赖之  解决方案
          网上的帖子千篇一律,基本都说不能解决,但我翻阅了一些资料,竟让我找到了线索,来~跟牛哥一起揭开它神秘的面纱。
          关键:打破循环的一种简单方法是说 Spring 懒惰地初始化其中一个 bean。也就是说:它不会完全初始化 bean,而是创建一个代理以将其注入另一个 bean。注入的 bean 只有在第一次需要时才会完全创建。
          要想完成此操作,必须对配置类(Config.class)进行以下更改:
            @Configuration
            public class Config {


            @Bean
            public ClassA classA(@Lazy ClassB classB) {
            return new ClassA(classB);
            }


            @Bean
            public ClassB classB(ClassA classA) {
            return new ClassB(classA);
            }
            }
            如果你现在运行测试,你将看到这次错误不会发生。

            Setter循环依赖_________

            最流行的解决方法之一,也是Spring 文档提出的,是使用 setter 注入。

            简单地说,如果你更改 bean 的连接方式以使用 setter 注入(或字段注入)而不是构造函数注入 - 这确实解决了问题。通过这种方式,Spring 创建了 bean,但在需要它们之前不会注入依赖项。(将ClassA、ClassB改成Setter方式,代码如下)

              public class ClassA {


              private ClassB classB;


              @Autowired
              public void setClassB(ClassB classB) {
              this.classB = classB;
              }


              public ClassB getClassB() {
              return classB;
              }
              }




              public class ClassB {


              private ClassA classA;


              private String message = "Hi!";


              @Autowired
              public void setClassA(ClassA classA) {
              this.classA = classA;
              }


              public String getMessage() {
              return message;
              }
              }

              配置类稍作修改:


                @Configuration
                public class Config {


                @Bean
                public ClassA classA() {
                return new ClassA();
                }


                @Bean
                public ClassB classB() {
                return new ClassB();
                }
                }
                测试

                  public class Test {
                  public static void main(String[] args) {
                  AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
                  ClassA classA = applicationContext.getBean(ClassA.class);
                  Assert.assertEquals("Hi!",classA.getClassB().getMessage());
                  }
                  }

                  注:断言的目的是确认是否正确注入,检查其消息属性的值。Setter循环依赖并不会报错

                  到此构造器循环依赖和Setter循环依赖就讲完了,希望以后的你越来越优秀,越来越美丽,加油吧,新时代农民工!!!


                  文章转载自程序员舒克,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论