问题说明
SpringBoot3.x
版本已经发布,从SpringBoot2.6.x
后就做了很多的改变。
用过SpringBoot2.7.5~x
版本的伙伴应该会发现,SpringBoot
项目中如果存在循环依赖关系,则在启动项目的时候会出现异常错误信息,提示内容大致为:项目中存在循环依赖,项目无法正常启动运行。
自SpringBoot2.7.5~x
版本以后至SpringBoot3.x
都存在这个问题,Spring
已经摒弃循环依赖的问题,需要开发人员自行解决,或在开发过程中尽量避免循环依赖的出现。
对于旧版本项目升级的来说,这将会是一件很棘手的问题,所有的存在循环依赖关系的代码都需要重新调整,况且一不小心就会代码崩溃无法运行。
解决方案
第一种、开启循环依赖(不推荐)
Spring默认已经不在支持循环依赖,在配置文件中重新开启循环依赖支持
spring:
main:
allow-circular-references:true #允许循环引用
第二种、懒加载
@Lazy:配合使用该注解可以解决循环依赖问题(在需要注入Bean的地方加上该注解)
@Lazy // 使用懒加载
@Autowired
private OneService oneService;
第三种、控制反转
@Service
@RequiredArgsConstructor // 该注解的使用在下面会有介绍和说明
public class OneServiceImpl implements OneService {
private final ConfigurableListableBeanFactory beanFactory;
//代替循环依赖
public TwoService getTwoService(){
return beanFactory.getBean(TwoService.class);
}
}
使用
getTwoService()
直接从bean工厂里面去拿对应的Bean来使用
@Service
@RequiredArgsConstructor // 该注解的使用在下面会有介绍和说明
public class TwoServiceImpl implements TwoService {
private final ConfigurableListableBeanFactory beanFactory;
//代替循环依赖
public OneService getOneService(){
return beanFactory.getBean(OneService.class);
}
}
以上代码中,OneService依赖于TwoService,而TwoService也依赖于OneService,从而产生循环依赖
解决:每次使用的时候就去Bean工厂里去获取,这样就不存在循环依赖了
@RequiredArgsConstructor使用说明
@RequiredArgsConstructor
:该注解是由Lombok
提供,可以解决掉大量重复的@Autowired
代码
注意:使用@RequiredArgsConstructor
时,需要使用final
关键字
写在类上可以代替@Autowired注解,需要注意的是在注入时需要用final定义,或者使用@notnull注解
@RestController
@RequiredArgsConstructor // 代替@Autowired注解
@RequestMapping("/api/v1/one")
public class OneController{
private final OneService oneService; // 需要final关键字
private final TwoService twoService; // 需要final关键字
@GetMapping("{id}")
public ResultVo<String> getDetails(@PathVariable("id") Long id){
return ResultVo.ok(oneService.getDetailsById(id));
}
}
注意点:
- 1、必须声明的变量为final。
- 2、根据构造器注入的,相当于容器调用带有一组带有参数的类构造函数时,基于构造函数的 DI 就完成了,其中每个参数代表一个对其他类的依赖。基于构造方法为属性赋值,容器通过调用类的构造方法将其进行依赖注入。
- 3、当需要注入Bean的时候可以直接在类名称上使用
@RequiredArgsConstructor
,从而代替了大量的@Autowrited
注解。