在学习 Spring Security 时,写代码写着写着,爆错了,显示的循环依赖,有种八股照进现实的感觉。
事情是这样的
当时的依赖调用链是这样的:
UserDetailsService->UserService->AuthenticationManager->UserDetailsService
当时写代码没想那么多,用 MyBatis-Plus 图省事,直接把UserService注入到了UserDetailsService里面。结果项目一启动,不出意外地直接报错报红了。
几种解决方法
针对这个问题,大概有这么几种处理方式:
注入
UserMapper- 不再通过
UserService绕一圈,直接在UserDetailsService里注入UserMapper查库。 - 优缺点:最简单直接。但从分层来看,安全层直接穿透到了 DAO 层,绕过了业务层。
- 不再通过
使用
@Lazy延迟加载- 在注入时加上
@Lazy,让 Spring 用代理对象打破初始化闭环。 - 优缺点:改动最小,不过感觉有点治标不治本。
- 在注入时加上
提取单独的
LoginService- 把包含
AuthenticationManager认证逻辑的部分抽离成一个独立的LoginService。 - 优缺点:结构最清爽,职责划分得比较开。
- 把包含
总结
要说哪个更好,感觉如果想让代码更规范一点,提取单独的LoginService应该是更好的选择了。
只能说,很多八股文里的东西没踩过坑还真体会不到,撞一次南墙印象就深刻了。