You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot整合Spring Security使用数据库数据认证时出现Bean循环依赖创建失败问题

Spring Boot整合Spring Security使用数据库数据认证时出现Bean循环依赖创建失败问题

嘿,我看到你在整合Spring Boot和Spring Security、用数据库数据做用户认证的时候碰到了循环依赖导致Bean创建失败的问题,这个坑我之前也踩过,咱们一步步来解决它~

首先,这个BeanCurrentlyInCreationException的核心原因是Spring容器在创建Bean的过程中出现了闭环依赖:比如SecurityConfig需要某个Bean,而那个Bean又反过来需要SecurityConfig,导致Spring不知道该先初始化哪个Bean。在Security整合场景里,最常见的就是SecurityConfig和自定义UserDetailsService、DataSource或者AuthenticationManager之间形成了循环。

下面是几个实用的解决方法,你可以根据自己的代码情况尝试:

  • 检查并调整依赖注入方式
    很多时候循环依赖是因为构造注入的顺序问题。比如如果你的SecurityConfig通过构造函数注入了自定义UserDetailsService,而这个UserDetailsService又间接依赖了和Security相关的Bean(比如AuthenticationManager),就容易出问题。你可以试试把构造注入改成Setter注入,或者在构造注入时给依赖加上@Lazy注解,让Spring延迟初始化那个依赖Bean:

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
        private UserDetailsService userDetailsService;
    
        // Setter注入替代构造注入
        @Autowired
        public void setUserDetailsService(UserDetailsService userDetailsService) {
            this.userDetailsService = userDetailsService;
        }
    
        // 或者构造注入时加@Lazy
        // public SecurityConfig(@Lazy UserDetailsService userDetailsService) {
        //     this.userDetailsService = userDetailsService;
        // }
    
        @Bean
        public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
            http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .formLogin(Customizer.withDefaults())
                .userDetailsService(userDetailsService);
            return http.build();
        }
    }
    
  • 确保自定义UserDetailsService的独立性
    你的自定义UserDetailsService应该只专注于从数据库查询用户数据,不要让它依赖SecurityConfig或者其他Security相关的Bean。比如如果需要操作数据库,直接注入JdbcTemplate或者DataSource就好,不要注入AuthenticationManager这类和Security配置绑定的Bean:

    @Service
    public class CustomUserDetailsService implements UserDetailsService {
        private final JdbcTemplate jdbcTemplate;
    
        // 只注入数据库操作相关的Bean
        public CustomUserDetailsService(JdbcTemplate jdbcTemplate) {
            this.jdbcTemplate = jdbcTemplate;
        }
    
        @Override
        public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
            // 从数据库查询用户名、密码、权限的逻辑
            String sql = "SELECT username, password, enabled FROM users WHERE username = ?";
            User user = jdbcTemplate.queryForObject(sql, new Object[]{username},
                (rs, rowNum) -> new User(
                    rs.getString("username"),
                    rs.getString("password"),
                    rs.getBoolean("enabled"),
                    true, true, true,
                    AuthorityUtils.createAuthorityList("ROLE_USER")
                )
            );
            if (user == null) {
                throw new UsernameNotFoundException("User not found: " + username);
            }
            return user;
        }
    }
    
  • 避免直接注入AuthenticationManager到其他Bean
    如果你需要使用AuthenticationManager,不要直接在其他Bean里注入它,而是通过AuthenticationConfiguration来获取,或者在SecurityConfig里把它定义为一个独立的Bean,这样可以避免循环:

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig {
        // ...其他配置
    
        @Bean
        public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
            return config.getAuthenticationManager();
        }
    }
    
  • 排查不必要的依赖
    仔细检查你的各个Bean的依赖关系,看看有没有不小心注入了不需要的Bean。比如有些同学会在UserDetailsService里注入SecurityConfig,这完全是多余的,直接去掉这类不必要的依赖就能解决循环问题。

按照上面的方法排查调整后,应该就能解决这个循环依赖的问题了。如果还是不行,可以把你的SecurityConfig和UserDetailsService的代码贴出来,咱们再进一步分析~

备注:内容来源于stack exchange,提问作者Bilolbek Rayimov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 09:54:37