当前位置: 首页 > news >正文

最近在刷牛客:使用Spring AOP实现性能监控时

题目:4.使用Spring AOP实现性能监控时,下列哪种方式无法获取方法执行时间?

A在@Around增强中通过ProceedingJoinPoint.proceed()调用前后计算时间差

B在@AfterReturning增强中通过JoinPoint获取方法开始时间戳

C使用@Before记录开始时间并存入ThreadLocal,在@After中计算耗时

D通过实现MethodInterceptor接口在invoke方法中计算执行时间

项目目标

  • 使用 Spring Boot

  • 演示4 种 AOP 方式

  • 验证哪一种不能获取方法执行时间

  • 结构清晰,适合练习和面试


一、项目结构(强烈建议你照着建)

spring-aop-demo ├── pom.xml └── src └── main └── java └── com └── example └── aopdemo ├── AopDemoApplication.java ├── service │ └── UserService.java ├── aspect │ ├── TimeAspect.java │ └── TimeInterceptorConfig.java └── interceptor └── TimeMethodInterceptor.java

二、pom.xml(完整)

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.1</version> <relativePath/> </parent> <groupId>com.example</groupId> <artifactId>spring-aop-demo</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <!-- Web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- AOP --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

三、启动类

package com.example.aopdemo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AopDemoApplication { public static void main(String[] args) { SpringApplication.run(AopDemoApplication.class, args); } }

四、业务类(被代理对象)

package com.example.aopdemo.service; import org.springframework.stereotype.Service; @Service public class UserService { public void login() throws InterruptedException { Thread.sleep(300); // 模拟方法执行 System.out.println("执行 login 方法"); } }

五、AOP 切面(核心)

package com.example.aopdemo.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Aspect @Component public class TimeAspect { /* ========== A. @Around(能统计时间) ========== */ @Around("execution(* com.example.aopdemo.service..*(..))") public Object around(ProceedingJoinPoint pjp) throws Throwable { long start = System.currentTimeMillis(); Object result = pjp.proceed(); long end = System.currentTimeMillis(); System.out.println("[Around] 耗时:" + (end - start)); return result; } /* ========== B. @AfterReturning(不能统计时间) ========== */ @AfterReturning("execution(* com.example.aopdemo.service..*(..))") public void afterReturning(JoinPoint jp) { System.out.println("[AfterReturning] 无法获取开始时间"); } /* ========== C. @Before + @After + ThreadLocal(能统计时间) ========== */ private static final ThreadLocal<Long> TIME = ThreadLocal.withInitial(System::currentTimeMillis); @Before("execution(* com.example.aopdemo.service..*(..))") public void before() { TIME.set(System.currentTimeMillis()); } @After("execution(* com.example.aopdemo.service..*(..))") public void after() { long cost = System.currentTimeMillis() - TIME.get(); System.out.println("[Before+After] 耗时:" + cost); TIME.remove(); } }

六、MethodInterceptor 方式(能统计时间)

1. 拦截器

package com.example.aopdemo.interceptor; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class TimeMethodInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { long start = System.currentTimeMillis(); Object result = invocation.proceed(); long end = System.currentTimeMillis(); System.out.println("[MethodInterceptor] 耗时:" + (end - start)); return result; } }

2. 配置类

package com.example.aopdemo.aspect; import com.example.aopdemo.interceptor.TimeMethodInterceptor; import org.springframework.aop.framework.ProxyFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TimeInterceptorConfig { @Bean public ProxyFactoryBean userServiceProxy(UserService userService) { ProxyFactoryBean factory = new ProxyFactoryBean(); factory.setTarget(userService); factory.addAdvice(new TimeMethodInterceptor()); return factory; } }

七、测试方式(最简单)

启动项目后访问:

GET http://localhost:8080/test

或者直接写测试类:

@SpringBootTest class AopDemoApplicationTests { @Autowired private UserService userService; @Test void testAop() throws InterruptedException { userService.login(); } }

八、你运行后会看到类似输出

[Around] 耗时:302 [Before+After] 耗时:302 [MethodInterceptor] 耗时:301 [AfterReturning] 无法获取开始时间 执行 login 方法

✅ 一眼就能验证B 是错误的

http://www.jsqmd.com/news/765732/

相关文章:

  • 通达信缠论可视化插件:3分钟快速上手终极指南
  • 为Claude Code编程助手配置Taotoken作为稳定后端的详细步骤
  • 终极Windows更新修复指南:为什么你需要这个专业重置工具
  • 别再乱用了!手把手教你区分高压放电场景下的绕线电阻、金属氧化膜电阻和陶瓷电阻
  • UniVideo:视频多模态统一建模的技术突破与应用
  • 8.7 搜索查找类
  • 21_手把手教你做AI漫剧实战篇
  • 音质进阶:FxSound提升音质的实用技巧分享
  • pywinauto实战:如何精准定位Windows桌面应用里的‘顽固’控件?(附Inspect工具使用技巧)
  • 鸿蒙 PC vs Windows:开发范式的本质区别
  • GEMMA跑GWAS遗传力总是不理想?试试这3个数据清洗和模型调整的实战技巧
  • R语言病害预警系统上线仅需48小时:从数据清洗到部署预测API的完整流水线
  • 终极指南:如何为Amlogic电视盒子刷入Armbian系统并解决网络兼容性问题
  • 百度网盘解析工具:3分钟搞定高速下载的完整指南
  • 别光记步骤!复盘Win2008 R2靶场:那些容易被忽略的DedeCMS和MySQL安全配置细节
  • 终极免费方案:如何让9大网盘下载速度突破限制
  • 你的旧安卓手机别扔!用Termux+Ubuntu把它变成24小时运行的轻量级服务器(内网穿透指南)
  • 请问天津水阀可以用吗
  • 毕业论文AI率高没钱降怎么办?免费试用4步省钱方案盘点! - 我要发一区
  • 大语言模型长文本处理:挑战、优化与实战方案
  • K8s里跑个Exporter就能监控vSphere?聊聊混合云监控的‘轻量级’实践
  • SkillKit:终结AI编程助手格式战争,实现技能跨平台统一管理
  • 小爱音箱AI升级终极指南:5分钟打造你的专属智能语音助手
  • HPH的构造 轻松看懂核心设计
  • 免费降AI率工具vs付费版:差距体现在哪5个核心维度? - 我要发一区
  • 嘎嘎降AI 1000字免费试用怎么用?6步操作流程教程详解! - 我要发一区
  • 从拉格朗日到欧拉:用FLUENT做两相流仿真,你的坐标系选对了吗?
  • 无换刀机械手的结构设计(说明书+CAD图纸)
  • 互联网大厂 Java 求职者面试:音视频场景中的微服务与 Spring Boot
  • 在内容生成业务中利用 Taotoken 实现多模型自动降级与路由