学习感悟,以及Spring中的循环依赖是如何解决的

4 篇文章 0 订阅

一、写在前面

上回书说到,spring中自动装配的关键注解@Autowired的原理,今天来给大家分享一下spring中的循环依赖问题以及该如何解决。我们之前写项目用到的mvc框架以及控制层、业务层、数据访问层三层架构的形式来编写项目,一环套一环,基本不会有什么问题,但在特殊情形下,确实可能出现循环依赖的问题,首先来解释一下什么是循环依赖。

二、循环依赖

1.定义:

循环依赖的定义很容易理解,假如有两个类:Demo01,Demo02,

代码如下:

@Component
public class Demo01 {



    private Demo02 circB;



    @Autowired
    public Demo01(Demo02 circB) {

        this.circB = circB;

    }

}
@Component
public class Demo02 {
    @Autowired
    private Demo01 circA;

    public Demo02(Demo01 circA) {

        this.circA = circA;

    }

}

然后再写一个配置类:

@Configuration
@ComponentScan(basePackages = { "com.example.demo.pojo" })
public class TestConfig {

}

可以看到,Demo01和Demo02互相依赖了对方,如果这样测试会发生什么呢

测试类:

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class })
 public class DemoApplicationTests {

    @Test
    public void ceshi() {
    }

}

在进行测试的时候,会弹出这样的报错:

意思是在 Demo01需要通过构造函数注入的Demo02实例(或者Demo02中声明的Bean),而Demo02需要通过构造函数注入的 Demo01的实例(或者 Demo01中声明的Bean)。如果将 Demo01和类Demo02的bean配置为相互注入,则Spring IoC容器会在运行时检测到此循环引用,并引发一个BeanCurrentlyInCreationException。与典型情况(没有循环依赖)不同,bean Demo01和bean Demo02之间的循环依赖关系迫使其中一个bean在被完全初始化之前被注入到另一个bean中。

听起来有点难以理解,但其实不难理解,我在做项目的时候,通常会有这样一种思想,把代码以及代码的运行想象成一条管道,首先管道通向哪里要明确,其次管道中的阻塞需要排除,而依赖注入就好像两个或者多个代码抢一个管道,毕竟spring框架又不是人,没法做到调度精确,所以如何解决循环依赖,就需要我们去想想办法。

2.解决方法

去网上查一查,发现有很多解决这问题的方法,我就挑一些简单易懂的来聊聊。

2.1重新设计

惹不起还躲不起了,把设计项目的人拉出来打一顿,或者把项目的层次结构设计地完善一点,不要出现类互相依赖,循环依赖的现象。当然这种方法只适合在项目初期以及你打得过项目经理的前提下。

2.2使用@Lazy

打破循环的一个简单方法是让Spring懒洋洋地初始化其中一个bean。那就是:它不是完全初始化bean,而是创建一个代理将它注入另一个bean。注入的bean只有在第一次需要时才会完全创建。

package com.example.demo.pojo;/*
@Author 涂碧宇写的代码
@since 2022/9/26
@version 1.0
*/

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class Demo01 {


    @Autowired
    private Demo02 circB;


    public Demo01( @Lazy Demo02 circB) {

        this.circB = circB;

    }

}

测试发现:

完美~

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值