写点什么

SpringBoot 升级所踩过的坑 (二)

作者:技术小生
  • 2023-06-08
    北京
  • 本文字数:1042 字

    阅读完需:约 3 分钟

SpringBoot 升级所踩过的坑 (二)

背景简介

因公司技术更迭,需要将项目统一升级到 SpringBoot2.7.8 版本。而项目中底层依赖的大版本升级,为日常的琐碎工作带来了技术挑战。写下系列文章,将自己在升级过程中遇到的问题以及解决方案,都一一记录下来,避免后人再度陷入泥潭。


问题描述

这次遇到的问题是循环依赖问题。Spring 使用三级缓存的方式解决了循环依赖。但是 SpringBoot2.6 版本之后,默认禁止了依赖循环引用。报错信息如下:

BeanCurrentlyInCreationException: Error creating bean with name 'XXService':

Requested bean is currently in creation: Is there an unresolvable circular reference?


解决方案

正是由于循环依赖使得代码变得极不优雅,所以在代码编写过程中,尽量避免循环依赖的发生。但是,一些历史代码,修改起来非常耗时,所以 Springboot 提供了开关,可以开启循环依赖引用。

  • 第一种方式,就是在启动项增加开关,启动命令如下:

java -jar XXX.jar --spring.main.allow-circular-references=true
复制代码

这种在服务启动的时候,直接允许循环依赖,Spring 就不会检验依赖关系。

  • 第二种方式,就是在配置文件中增加配置项,配置文件为 properties 文件时,配置如下:

spring.main.allow-circlar-references = true
复制代码

这样也能防止循环依赖的发生,但是如果配置项是通过配置中心(Apollo、Nacos)等加载的话,该配置需要在配置中心的类加载后,才能加载配置,对于类加载的循环依赖问题可能不会生效。

  • 第三种方式,在调用链末端的 bean 初始化时,引用 Bean 的地方增加 @Lazy 注解,使该类的加载延迟进行。比如:

The dependencies of some of the beans in the application context form a cycle:
classCourseService homeworkMarkTplService┌─────┐| preparationCommonService↑ ↓| teachingPreparationOverviewCommonService↑ ↓| teachingPreparationInitService↑ ↓| promptService└─────┘
PromptService 里引用 PreparationCommonService 时,如下: @Resource @Lazy private PreparationCommonService preparationCommonService;
复制代码

代码中如果使用 pagehelper 时,如果使用的是低版本的,也会报引用循环依赖问题。这时,将依赖包版本升级到 1.4.6 即可解决。


早期 Spring 允许循环依赖配置,但是发现循环依赖严重的话,代码可读性变差。所以,在高版本 Spring 中默认禁止了该行为。为了代码美观、易读,还是思考好代码结构,避免循环依赖。下集再聊一下升级过程中其他的坑。

发布于: 刚刚阅读数: 3
用户头像

技术小生

关注

业务应用架构专家 2019-10-08 加入

主要负责公司内部系统的应用架构设计与落地。擅长Java语言开发,熟悉Python、Shell等。精通K8S等云原生相关技术。

评论

发布
暂无评论
SpringBoot 升级所踩过的坑 (二)_6月优质更文活动_技术小生_InfoQ写作社区