Spring Boot 3.0.6循环依赖问题解决(避免开启循环依赖允许配置)
为什么Spring不鼓励循环依赖,以及解决你的循环依赖问题
一、为什么不鼓励循环依赖
- 耦合度过高:类之间互相绑定,修改其中一个类可能牵连多个关联类,维护成本急剧上升。
- 初始化风险:Spring创建Bean时会陷入循环死锁,即便开启允许循环依赖,也可能出现Bean未完全初始化就被调用的情况,触发空指针或逻辑异常。
- 设计缺陷信号:循环依赖大多意味着代码职责划分模糊,违反了单一职责、依赖倒置等设计原则,代码可读性和扩展性极差。
二、解决你的循环依赖问题
从你的依赖链和代码来看,循环的根源是:WebConfig → LoginCheckInterceptor → SessionLoginService → GeneralMemberService → PasswordEncoder(来自WebConfig的@Bean),形成闭环。
最优解决方案:拆分Bean配置
把PasswordEncoder的Bean从WebConfig中移到独立配置类,直接打破依赖链:
- 创建独立配置类(比如
SecurityConfig):
@Configuration public class SecurityConfig { @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
- 删除
WebConfig中的passwordEncoder()方法,保留原有逻辑:
@Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { private final LoginCheckInterceptor loginCheckInterceptor; private final LoginMemberArgumentResolver loginMemberArgumentResolver; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginCheckInterceptor) .addPathPatterns("/**") .excludePathPatterns("/members/register", "/members/sign-in", "/api/posts", "/api/posts/*"); } @Override public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { resolvers.add(loginMemberArgumentResolver); } }
这样GeneralMemberService依赖的PasswordEncoder不再与WebConfig绑定,循环依赖直接被打破,同时代码结构更清晰,符合单一职责原则。
可选临时方案:延迟加载(不推荐长期使用)
如果不想调整配置结构,可以给某个依赖添加@Lazy注解延迟Bean初始化,比如在WebConfig中注入拦截器时:
@Configuration @RequiredArgsConstructor public class WebConfig implements WebMvcConfigurer { private final @Lazy LoginCheckInterceptor loginCheckInterceptor; private final LoginMemberArgumentResolver loginMemberArgumentResolver; // 其他代码不变 }
但这种方法只是绕过问题,并未解决代码设计上的耦合,建议优先采用拆分配置的方案。
长远优化:精简依赖
观察你的LoginCheckInterceptor,它只用到了LoginService的getLoginMemberId()方法,而该方法仅从HttpSession取ID,完全不需要依赖MemberService。可以考虑拆分LoginService职责:
- 抽离
LoginSessionService接口,仅包含getLoginMemberId()、logout()等Session相关方法; - 让
LoginCheckInterceptor依赖这个精简接口,而非完整的LoginService; - 原
SessionLoginService同时实现这个精简接口和原LoginService。
这种方式能进一步降低依赖耦合,从根源上避免类似问题。
内容的提问来源于stack exchange,提问作者Jaeyeon
相关产品推荐
相关产品推荐

