springboot 循环依赖

阅读数:135 评论数:0

跳转到新版页面

分类

python/Java

正文

一、概述

循环依赖是指在Spring Boot 应用程序中,两个或多个类之间存在彼此依赖的情况,形成一个循环依赖链。当一个类在初始化时需要另一个类的实例,而另一个类又需要第一个类的实例时,就会出现循环依赖问题。

1、spring初始化bean的步骤

2、构造函数注入、set注入、属性注入

public class HelloController {
  
        @Autowired
    private BeanA a;
    
    private BeanB b;

    @Autowired
    public void setB(BeanB b) {
        this.b = b;
    }

    private final BeanC c;
    
//    @Autowired
    public HelloController(BeanC c) {
        this.c = c;
    }
}

当一个类只有一个构造函数时,可以省略@Autowired的注释。

@AllArgsConstructor和final 代替 @Autowired。

二、解决方法

spring通过三级缓存机构来解决循环依赖问题。

1、spring的三级缓存

singletonObjects 单例对象的cache
singletonFactories 单例对象工厂的cache
earlySingletonObjects 提前暴光的单例对象的Cache

spring在创建Bean A的时候会先去一级缓存(singletonObjects),如果一级缓存没有则再从二级缓存(earlySingletonObjects)中获取,如果二级缓存也没有,则再从三级缓存(singletonFactories)中获取,如果还获取不到,则实例化一个A,然后放入三级缓存,然后填充属性,此刻发现依赖B,于是创建B,同样的经过上述步骤,由于每级缓存都获取不到,于是实例化B,然后填充属性,发现依赖A,然后依次去每级缓存中获取,由于三级缓存中已经有一个A,于是B可以顺利注入依赖,并被正确的初始化,然后递归返回,于是A也可以被正确的初始化了。

通过上述说明,可以看出bean都是需要可以先被实例化才可以的,所以这也就是为什么构造器依赖可能会失败的原因。假如A构造器依赖B,因为实例化A需要先调用A的构造函数,发现依赖B,那么需要去初始化B,但是B也依赖A,不管B是通过构造器注入还是setter注入,此时由于A没有被实例化,没有放入三级缓存,所以B无法被初始化,所以spring会直接报错。反之,如果A通过setter注入的话,那么则可以通过构造函数先实例化,放入缓存,然后再填充属性,这样的话不管B是通过setter还是构造器注入A,都能在缓存中获取到,于是可以初始化。

2、基于三级缓存,推荐的解决方法

(1)Setter注入

使用setter方法注入依赖项,而不是在构造函数中注入。

(2)延迟注入

使用@Lazy注解延迟加载依赖项。

(3)@Autowired注解的required属性

 将required属性设置为false,以避免出现循环依赖问题。

(4)@DependsOn注解

使用@DependsOn注解指定依赖项的加载顺序,以避免出现循环依赖问题

 




相关推荐

一、request uri部分 @PathVariable 获取路径参数,形如url/{id} 二、request header部分 @RequestHeade

一、概述 一个项目使用多个数据库(无论是主从复制--读写分离还是分布式数据库结构)的重要性变得越来越明显,整合的多数据源有两种方式:分包和aop。 1、SqlSessionTemplate SqlSe

一、概述 PageHelper是开源免费的mybatis第三方分页插件。 二、使用 1、pom引入 <dependency> <groupId>com.github.pageh

一、日志框架的介绍 Spring Boot 2.*默认采用slf4j+logback的形式,slf4j是个通用的日志门面,logback就是个具体的日志框架了。

一、问题解决方式 @PostMapping("/insert") @ResponseBody private ResultVO insert1(@RequestParam Map<String, St

JJWT 全称Java Json Web Token。 而JWT是一种在两方之间传输信息的方法,在jwt的主体中编码的信息被称为claims。jwt的扩展形式是json,因此每个c

POM依赖 &lt;dependency&gt; &lt;groupId&g

一、概述 @EnableConfigurationProperties注解的作用是:让使用了@ConfigurationProperties注解的类生效,并且将该类注入到IOC容器中,交由IOC容器进

Spring IoC容器一般会在启动的时候实例化所有单实例bean。如果我们想要Spring在启动的时候延迟加载bean,即在调用某个bean的时候再去初始化,那么就可以使用@Lazy注解。</

一、概述 Druid(德鲁伊)是Java语言中的数据库连接池,Spring Boot 2.x默认使用Hikari数据源,虽然HikariCP的速度稍快,但是,Druid能够提供强大的监控和扩展功能。