2024.11.12

news/2024/11/14 9:50:22/文章来源:https://www.cnblogs.com/258-333/p/18542825

主要问题:

SecurityHandlerhandlerOnAuthenticationSuccess 方法中调用了 userService.userLoginStatus,这会导致 UserService 需要依赖 SecurityHandler。这种双向依赖形成了一个循环依赖,Spring 容器无法正确处理这个循环,导致应用启动失败。

解决思路:

1. 避免循环依赖

通过重构代码,消除这种循环依赖。常见的做法是将其中某个依赖提取出来,或改变它们的关系。以下是几种可能的解决方法:

方法 1:延迟加载 UserService

如果 UserService 仅在 SecurityHandler 中的某些方法中使用,你可以使用 @Lazy 注解来延迟加载 UserService,从而避免循环依赖。

代码修改如下:

@Component
@RequiredArgsConstructor
public class SecurityHandler {@Resourceprivate JwtUtils jwtUtils;@Resourceprivate RedisCache redisCache;@Resourceprivate LoginLogService loginLogService;@Resource@Lazy  // 延迟加载,避免循环依赖private UserService userService;public void handlerOnAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response,LoginUser user) {String typeHeader = request.getHeader(Const.TYPE_HEADER);if ((!StringUtils.matches(typeHeader, List.of(Const.BACKEND_REQUEST, Const.FRONTEND_REQUEST)) && user.getUser().getRegisterType() == 1)) {throw new BadCredentialsException("非法请求");}Long id = user.getUser().getId();String name = user.getUser().getUsername();// UUID做jwt的idString uuid = UUID.randomUUID().toString();// 生成jwtString token = jwtUtils.createJwt(uuid, user, id, name);// 转换VOAuthorizeVO authorizeVO = user.getUser().asViewObject(AuthorizeVO.class, v -> {v.setToken(token);v.setExpire(jwtUtils.expireTime());});// 如果可以,尽量避免这里直接调用 UserService 的方法,改成通过事件或消息中间件等方式解耦userService.userLoginStatus(user.getUser().getId(), user.getUser().getRegisterType());loginLogService.loginLog(request, request.getParameter(USER_NAME), 0, RespConst.SUCCESS_LOGIN_MSG);WebUtil.renderString(response, ResponseResult.success(authorizeVO, RespConst.SUCCESS_LOGIN_MSG).asJsonString());}
}

使用 @Lazy 注解后,UserService 在初始化时不会立即注入,而是等到需要时才会被注入,从而避免了构造时的循环依赖问题。

方法 2:重构 SecurityHandlerUserService 的依赖关系

另一种方式是重构 SecurityHandlerUserService 的关系,避免它们之间直接的依赖。如果 UserServiceSecurityHandler 中有互相依赖的功能,可以考虑通过引入一个新的中间服务来拆解这两个类之间的关系。例如,将 userLoginStatus 方法移到一个新的业务类中,而不是放在 UserService 中。

@Service
public class UserStatusService {private final UserService userService;@Autowiredpublic UserStatusService(UserService userService) {this.userService = userService;}public void updateUserLoginStatus(Long userId, int registerType) {// 这里执行用户登录状态更新userService.userLoginStatus(userId, registerType);}
}@Component
@RequiredArgsConstructor
public class SecurityHandler {@Resourceprivate JwtUtils jwtUtils;@Resourceprivate RedisCache redisCache;@Resourceprivate LoginLogService loginLogService;@Resourceprivate UserStatusService userStatusService;public void handlerOnAuthenticationSuccess(HttpServletRequest request,HttpServletResponse response,LoginUser user) {String typeHeader = request.getHeader(Const.TYPE_HEADER);if ((!StringUtils.matches(typeHeader, List.of(Const.BACKEND_REQUEST, Const.FRONTEND_REQUEST)) && user.getUser().getRegisterType() == 1)) {throw new BadCredentialsException("非法请求");}Long id = user.getUser().getId();String name = user.getUser().getUsername();// UUID做jwt的idString uuid = UUID.randomUUID().toString();// 生成jwtString token = jwtUtils.createJwt(uuid, user, id, name);// 转换VOAuthorizeVO authorizeVO = user.getUser().asViewObject(AuthorizeVO.class, v -> {v.setToken(token);v.setExpire(jwtUtils.expireTime());});// 使用新的 UserStatusService 来处理登录状态userStatusService.updateUserLoginStatus(user.getUser().getId(), user.getUser().getRegisterType());loginLogService.loginLog(request, request.getParameter(USER_NAME), 0, RespConst.SUCCESS_LOGIN_MSG);WebUtil.renderString(response, ResponseResult.success(authorizeVO, RespConst.SUCCESS_LOGIN_MSG).asJsonString());}
}

在这种方式下,SecurityHandler 不再直接依赖 UserService,而是依赖 UserStatusService,从而打破了循环依赖。

方法 3:使用事件驱动方式

如果 userService.userLoginStatus() 是一个异步操作或者涉及到其他业务逻辑,可以考虑使用 Spring 的 事件驱动模型 来解耦这个过程。你可以发布一个事件,并在另一个类中监听这个事件来执行相关逻辑。这样可以进一步解耦类与类之间的依赖关系。

总结:

  • 使用 @Lazy 注解:最简单的一种解决循环依赖的方法,适用于延迟加载的场景。
  • 重构依赖关系:将一个类中的某些依赖移到其他服务中,避免直接的循环依赖。
  • 事件驱动:如果操作是异步的,可以考虑通过发布/订阅机制来解耦操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/832523.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Alpha冲刺阶段博客

数字电路模拟游戏团队 Alpha冲刺阶段博客 一、Scrum Meeting 第六周会议记录 第七周会议记录 二、测试报告 Alpha阶段测试报告 三、习得的软工原理/方法/技能? 1. 迭代开发与持续集成 采用迭代开发模式可以极大的提高开发效率,降低开发成本,迭代开发是一种增量式的软件开发方…

【shell脚本】了解一下shell中的主机变量和本地语系变量

简单介绍一下在 shell 脚本中的主机变量和本地语系变量。 版本和主机信息变量 shell 内置了一些变量,用于记录主机、硬件、操作系统等信息。这些变量如下:本地语系变量这些变量的优先级关系为:LC_ALL > LC_* > LANG ​原创 模糊的程序员

DVWA SQL注入union

数字型注入 1 and 1=1 1 and 1=2 返回数据不一样则有注入点且为数字型注入 //判断列数 ?id=and 1 order by 6 //返回正确 ?id=and 1 order by 7 //返回错误 得到列数为6 查数据库:1 and 1=2 union select 1,database() 字符型注入 and 1=1 and1=1 and 1=2 and1=1 ?id=…

痞子衡嵌入式:关于恩智浦SDK2.0里事务型中断处理函数(DriverIRQHandler)的重定向注意事项

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是SDK2.0里事务型中断处理函数(DriverIRQHandler)的重定向注意事项。最近有一个 i.MXRT 客户在使用官方 SDK 外设驱动里的中断处理函数时遇到了代码重定向失效问题,客户用得是一个 XIP Flash 工程,想把程序中…

基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现六

部分功能:课程信息业务逻辑层Service、课程分类信息业务逻辑层Service、课程订单信息业务逻辑层Service、课程小节信息业务逻辑层Service、课程评论信息业务逻辑层Service 技术点:SpringBoot+SpringDataJPA+Mysql+Freemaker+Bootstrap+JS+CSS+HTML一、前言介绍: 免费获取:猿…

基于Java+SpringBoot+Mysql在线课程学习教育系统功能设计与实现五

技术点:SpringBoot+SpringDataJPA+Mysql+Freemaker+Bootstrap+JS+CSS+HTML 部分功能:前台用户信息数据层Dao、公告信息数据层Dao、评论信息数据层Dao、常见问题信息数据层Dao、优惠卷信息数据层Dao、论坛信息数据层Dao、论坛回复信息数据层Dao、学习资料信息数据层Dao、充值记…

全局平衡二叉树 (GBST) 小记

全局平衡二叉树 (GBST) 小记 以下全局平衡二叉树简称 \(\text{GBST(Globel Balanced Search Tree)}\)。 我认识的大多数人,对 \(\text{GBST}\) 的理解基本上都是 静态 \(\text{LCT}\),或者静态 \(\text{Top Tree}\),不过我对 \(\text{LCT}\) 的理解可能还差一点,所以我不打…

考研打卡(15)

开局(15) 开始时间 2024-11-12 20:37:51 结束时间 2024-11-12 22:41:32现在在敷泥膜数据结构设已知一稀疏矩阵的三元组表为:(1,2,3),(1,6,1),(3,1,5),(3,2,-1) (5,4,5),(5,1,-3),则其转置矩阵的三元组表中的第三个三元组为____(山东大学2013年) A (2,…

25. 使用MySQL之使用触发器

1. 触发器 MySQL语句在需要时被执行,存储过程也是如此。但是,如果你想要某条语句(或某些语句)在事件发生时自动执行,怎么办呢?例如:每当增加一个顾客到某个数据库表时,都检查其电话号码格式是 否正确,州的缩写是否为大写;每当订购一个产品时,都从库存数量中减去订购…

Mysql表分区实操

创建分区表 create table user(id int(11) not null,name varchar(32) not null) partition by range(id) ( partition p0 values less than(10), partition p1 values less than(20), partition p2 values less than(30), partition p3 values less than maxvalue )分区表数据…

【Azure Bot Service】部署NodeJS ChatBot代码到App Service中无法自动启动

问题描述 把NodeJS的ChatBot代码部署到App Service环境中,通过VS Code直接部署,显示部署成功。但是通过URL访问时候,却是 :( Application Error 。问题解答 App Service遇见Application Error,第一步,查看日志。 发现启动时候遇见: 2024-11-12T12:22:40.366223350Z Error…

Chrome如何卸载掉插件?如此简单!

前言 我之前由于好奇,一下子装了很多的chrome插件,这些插件虽然都有很多功能,但是,由于我的电脑性能不佳,浏览器一下子装这么多插件,有点带不动了。所以,我就想到了卸载谷歌浏览器,哦不,是卸载浏览器里面的插件。今天,我就来介绍下,如何在chrome里面卸载一些不常用的…