一、循环依赖问题
APPLICATION FAILED TO START
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| springSecurityConfig (field private XXXX.config.MyauthenticationProvider XXXX.config.SpringSecurityConfig.myauthenticationProvider)
↑ ↓
| myauthenticationProvider (field private org.springframework.security.crypto.password.PasswordEncoder XXXX.config.MyauthenticationProvider.passwordEncoder)
└─────┘
Action:
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
进程已结束,退出代码为 0
二、背景说明
最近也没有啥变更啊,有的就是因为客户漏洞扫描的时候,反馈了说我们的Spring框架出问题了,第一直接就是SpringBoot的版本有问题,要修复,于是升级了版本如下,这一升级,好啦,就出现了上面的问题了。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.7</version>
<relativePath/>
</parent>
底层默认的Spring版本是
<spring-framework.version>5.3.19</spring-framework.version>
三、问题原因
3.1 在SpringSecurityConfig注入MyAuthenticationProvider
@Autowired
private MyAuthenticationProvider myAuthenticationProvider;
3.2 在SpringSecurityConfig声明一个Bean,PasswordEncoder
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
3.2 在MyAuthenticationProvider 又注入了PasswordEncoder
@Component
public class MyAuthenticationProvider implements AuthenticationProvider, UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private UserDao userDao;
@Autowired
private PasswordEncoder passwordEncoder;
四、问题解决
循环引用主要是因为会导致Spring不知道该先创建哪个Bean才会被禁用的,可以使用@Lazy
注解指定某个Bean进行懒加载就可以优雅解决该问题。
@Component
public class MyAuthenticationProvider implements AuthenticationProvider, UserDetailsService {
@Autowired
private UserService userService;
@Autowired
private UserDao userDao;
@Lazy
@Autowired
private PasswordEncoder passwordEncoder;
五、@Lazy注解
5.1 @Lazy的定义
翻译过来是"懒惰的",即@Lazy(懒加载)
5.2 @Lazy的作用
该注解用于惰性加载初始化标注的类、方法和参数。
5.3 @Lazy的应用场景
在Spring中常用于单实例Bean对象的创建和使用;
单实例Bean懒加载:容器启动后不创建对象,而是在第一次获取Bean创建对象时,初始化。