场景
写权限模块-登录验证这一块的时候,遇到了一个比较有意思的问题,循环依赖:
The dependencies of some of the beans in the application context form a cycle:
userController defined in file xxx
↓
userServiceImpl defined in file xxxx
┌─────┐
| EmailRegisterStrategy defined in file xxx
└─────┘
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.
Disconnected from the target VM, address: '127.0.0.1:12613', transport: 'socket'
Process finished with exit code 1
平时面试的时候,经常问人循环依赖怎么解决,八股文有说:
在 Spring Boot 的配置文件中启用循环引用。
spring:
main:
allow-circular-references: true
或者开启Lazy注解云云,如果有面试官这么问我,我可能要开启嘲讽模式,因为这几种方案都不是解决循环依赖的最佳策略,除非代码不需要维护或者公司就他一个开发~
WHY?为什么不推荐使用?WHY?
首先我们需要知道,一般的代码中肯定不会出现循环依赖,我这里出现是因为我的email调用了我的service中发送和检查的方法,这显然本身就不是合理的。
使用 spring.main.allow-circular-references: true 的问题
如果我使用 spring.main.allow-circular-references: true 来解决问题,将会出现以下的问题:
- 我刚刚提到了,我的设计不太合理,如果允许循环依赖会隐藏代码中的设计缺陷,并且后面可能会引发更多缺陷,我可以肆无忌惮的在Service中加东西 ,导致代码越来越差劲,后面拓展根本没办法拓展。
- 性能问题,循环依赖会导致性能问题,当依赖注入涉及大量的懒加载或延迟初始化时那么性能会出现大问题。
使用 @Lazy 注解的问题
这么聊吧,这是最 “可爱”的解决方案,小可爱都喜欢用,如果在什么ERP,什么OA使用那还好,如果在我们这种AI-ROBOT项目中使用,等于作死,懒加载的对象可能会引入不可预见的问题,尤其是在高并发或多线程环境中。
懒加载的代码约等于如下:
public class LazyLoadedService {
private static Service instance;
public static Service getInstance() {
if (instance == null) {
instance = new Service(); // Potential race condition
}
return instance;
}
}
- 懒加载对象的初始化通常在首次访问时进行。如果多个线程同时访问一个尚未初始化的懒加载对象,可能会导致多个线程同时尝试初始化这个对象,从而引发线程安全问题。
- 当然了我们初始化一个机器人会经过大量的操作,如果用这玩意,用户会爆炸,并且会拒绝我们后续所有产品。因为:在高并发环境中,懒加载会导致初次执行时间大大增加,十分的影响性能。系统直接挂B(当然了,是在用户眼里)。
- 懒加载对象的初始化过程需要获取其他资源的锁,而这些资源的获取又依赖于当前线程持有的锁,会导致死锁。
- 喜闻乐见的内存问题,我就职于上一家单位的时候,解决不下3次生产的内存问题,每天搞到两三点,一行行去找代码才解决了,内存问题分为两种,内存溢出和内存泄漏导致的溢出,小可爱们喜欢在Map中套List,List中在引入一些杂七杂八的,这个Map和里面的东西的生命周期快赶上程序的生命周期了,当然了,懒加载对象如果没有被正确管理,会导致内存泄漏。在高并发环境下,如果大量的对象被懒加载但没有被正确释放,可能会导致内存使用迅速增加。导致宕机(这是会死人的)
最终解决
那么,有人可能会问,那我应该怎么解决呢???
答:如果你是准备面试,以上两种可爱的方案,你自己可以当然可以回答,如果你不喜欢你的公司,那么也可以使用,但是,如果你是在生产环境,你又比较看重工作,解决方案只有一个,重构循环依赖那部分的代码,别嫌麻烦,这是解决最快也是最没有隐患的一条路线!!!
结束语
去重构登录这部分代码去了!