Boot升级到2.6后出现BeanCurrentlyInCreationException

Ger*_*oza 11 spring spring-security spring-boot

将我的项目升级到 Spring Boot 后2.6.0,我​​在启动过程中遇到以下异常:

org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'webSecurityConfig': Requested bean is currently in creation: Is there an unresolvable circular reference?
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.beforeSingletonCreation(DefaultSingletonBeanRegistry.java:355) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:227) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1352) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1195) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.13.jar:5.3.13]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.13.jar:5.3.13]
Run Code Online (Sandbox Code Playgroud)

但是,我的配置似乎符合 Spring 文档(HttpSecurity setupAuthenticationManagerBuilder setupPasswordEncoder setup):

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .mvcMatchers("/presentations")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .formLogin();
    }
    
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
            .withUser("testuser")
            .password(encoder().encode("password"))
            .roles("READ");
    }

    @Bean
    public PasswordEncoder encoder() {
        return new BCryptPasswordEncoder();
    }
}
Run Code Online (Sandbox Code Playgroud)

Ger*_*oza 19

仔细查看我的实现,似乎@Autowired调用该方法的方法@Bean PasswordEncoder正在生成此问题(如果我从另一个定义方法中调用该方法,则不会发生这种情况@Bean)。

解决方案是将逻辑移至不同的@Configuration类:

@Configuration
public class UsersSetup {
    
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth, PasswordEncoder encoder) throws Exception {
        auth.inMemoryAuthentication()
        .withUser("testuser")
        .password(encoder.encode("password"))
        .roles("READ");
    }
}
Run Code Online (Sandbox Code Playgroud)

之所以在新的 Boot 版本中出现这种情况,是因为默认情况下 Boot 现在不再尝试自动打破依赖循环:

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes#circular-references-prohibited-by-default

作为替代方案,我还可以通过在项目中包含以下应用程序属性来将此功能恢复为以前的行为:

spring.main.allow-circular-references=true
Run Code Online (Sandbox Code Playgroud)

  • 或者,您可以将密码编码器的工厂方法声明为“static”。这允许坚持使用一个配置类来配置 Spring Security。 (7认同)