😄 19年之后由于某些原因断更了三年,23年重新扬帆起航,推出更多优质博文,希望大家多多支持~
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志
🎐 个人CSND主页——Micro麦可乐的博客
🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战
🌺《RabbitMQ》专栏主要介绍使用JAVA开发RabbitMQ的系列教程,从基础知识到项目实战
🌸《设计模式》专栏以实际的生活场景为案例进行讲解,让大家对设计模式有一个更清晰的理解
💕《Jenkins实战》专栏主要介绍Jenkins+Docker的实战教程,让你快速掌握项目CI/CD,是2024年最新的实战教程
🌞《Spring Boot》专栏主要介绍我们日常工作项目中经常应用到的功能以及技巧,代码样例完整
如果文章能够给大家带来一定的帮助!欢迎关注、评论互动~
Spring Boot 实现 AOP 动态热插拔功能并附DEMO源码
- 前言
- 应用场景
- 开始实战
- ❶ 初始化项目
- ❷ 创建自定义注解
- ❸ 定义配置管理类
- ❹ 定义切面类
- ❺ 使用切面
- ❻ 创建测试Controller
- ❼ 测试效果
- 总结
前言
本文对应代码下载地址:https://download.csdn.net/download/lhmyy521125/89504659 无需积分!
AOP
(面向切面编程)是一种强大的编程范式,可以用于日志记录
、性能监控
、安全检查
等跨越多个模块的通用功能。实现 AOP
的动态热插拔可以让我们在不重启应用的情况下启用
或禁用
特定的切面,提高系统的灵活性和可维护性。
我们以一个例子来说明一下为什么需要 AOP
动态热插拔:我们系统有一个 AOP
切面,它负责了记录用户传递参数、执行时间、接口返回结果,默认是不开启的,现在因为某些原因需要检测某个接口参数接收情况 + 耗时 + 返回数据,那么我们就需要在不重启应用的情况下,动态开启关闭AOP切面来达到我们想要的效果。
本文就跟着博主一起来学习在 Spring Boot
中实现 AOP
的动态热插拔功能。
应用场景
动态热插拔功能适用的场景有很多,这里简单举例几个场景:
-
1、调试和排查问题:在生产环境中
临时启用日志或性能监控切面
,以便快速定位问题。例如,当发现某个服务的响应时间突然增加时,可以动态启用性能监控切面,记录每个方法的执行时间,从而找出性能瓶颈。 -
2、动态功能开关:根据业务需求
动态启用或禁用
某些功能,如限流
、鉴权
等。例如,在高流量的促销活动期间,可以临时启用限流切面,防止服务器过载。在活动结束后,可以动态关闭限流切面,恢复正常流量处理。 -
3、性能优化:在高负载时关闭一些耗性能的切面以提高系统吞吐量。例如,在系统的非高峰期,可以启用详细的日志记录和审计切面,以便收集用户行为数据和系统操作日志。而在系统高峰期,可以临时关闭这些切面,以减少日志记录带来的性能开销。
-
4、安全审计:在面对安全审计或合规检查时,可以临时启用安全检查切面,记录所有的安全相关操作。例如,在接到安全审计通知时,可以动态启用安全检查切面,记录所有用户的登录和数据访问行为,确保审计数据的完整性。
-
5、实验和AB测试:在进行新功能的实验和AB测试时,可以动态控制某些功能的启用。例如,在推出新功能时,可以动态启用或禁用相关切面,控制新功能的实验组和对照组,从而评估新功能的效果和性能影响。
开始实战
废话了那么多,我们还是以代码样例来进行演示讲解
❶ 初始化项目
首先,创建一个新的 Spring Boot 项目,在在 pom.xml
文件中添加相关依赖
<dependencies><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Spring Boot Starter AOP --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
</dependencies>
❷ 创建自定义注解
package com.toher.project.dynamic;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Loggable {
}
❸ 定义配置管理类
定义一个配置管理类,主要作用是控制AOP
开关
package com.toher.project.dynamic;import org.springframework.stereotype.Component;@Component
public class AspectConfig {private boolean loggingEnabled = true;public boolean isLoggingEnabled() {return loggingEnabled;}public void setLoggingEnabled(boolean loggingEnabled) {this.loggingEnabled = loggingEnabled;}
}
❹ 定义切面类
定义一个切面类,模拟业务耗时打印的功能
package com.toher.project.dynamic;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {@Autowiredprivate AspectConfig aspectConfig;@Around("@annotation(com.toher.project.dynamic.Loggable)")public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {if (!aspectConfig.isLoggingEnabled()) {return joinPoint.proceed();}long start = System.currentTimeMillis();Object proceed = joinPoint.proceed();long executionTime = System.currentTimeMillis() - start;System.out.println(joinPoint.getSignature() + " 方法执行时间 " + executionTime + "ms");return proceed;}
}
❺ 使用切面
编写一个 service
,在需要记录日志的方法上使用 @Loggable
注解
package com.toher.project.dynamic;import org.springframework.stereotype.Service;@Service
public class UserService {@Loggablepublic void performOperation() {// 业务逻辑System.out.println("执行相关操作...");}
}
❻ 创建测试Controller
接下来编写一个Controller
主要用于测试,开关AOP
的日志时间打印功能
package com.toher.project.dynamic;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;@RestController
@RequestMapping("/api/config")
public class ConfigController {@Autowiredprivate AspectConfig aspectConfig;@Autowiredprivate UserService userService;/*** 测试AOP执行* @return*/@GetMapping("/logging")public String isLoggingEnabled() {userService.performOperation();return "SUCCESS 当前loggingEnabled为 " + aspectConfig.isLoggingEnabled();}/*** 开关AOP日志耗时记录功能* @param enabled*/@PostMapping("/logging")public String setLoggingEnabled(@RequestParam boolean enabled) {aspectConfig.setLoggingEnabled(enabled);return "更新成功当前loggingEnabled为 " + aspectConfig.isLoggingEnabled();}
}
❼ 测试效果
运行Spring Boot
项目,博主使用 Apifox
访问 http://localhost:端口号/api/config/logging
观察控制台输出
修改我们的loggingEnabled
修改后再次观察控制台,发现当 loggingEnabled = false
本次并没有执行耗时打印功能
总结
通过上述简单的DEMO相信大家已经初步了解了实现 AOP
动态热插拔功能,DEMO代码仅仅为了演示,实际上我们项目中还可以考虑以下几点:
- 配置持久化:可以将配置状态存储在数据库或其他持久化存储中,确保应用重启后配置不丢失。
- 丰富的控制接口:根据实际需求,可以扩展 REST 接口,增加对多个切面和更多配置项的管理。
- 细粒度控制:在切面逻辑中可以根据更多条件(如请求参数、用户角色等)进行更细粒度的控制。
本篇文章我们实现了 Spring Boot
项目中 AOP
切面的动态热插拔功能。关键点在于通过配置管理类动态控制切面的启用状态,并在切面逻辑中根据状态决定是否执行切面代码。这样可以在不重启应用的情况下动态调整应用行为,提高系统的灵活性和可维护性。
如果本文对您有所帮助,希望 一键三连 给博主一点点鼓励,如果您有任何疑问或建议,请随时留言讨论!