最近在刷牛客:使用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 version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version3.2.1/version relativePath/ /parent groupIdcom.example/groupId artifactIdspring-aop-demo/artifactId version1.0-SNAPSHOT/version dependencies !-- Web -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- AOP -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-aop/artifactId /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-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 ThreadLocalLong 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([BeforeAfter] 耗时 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 [BeforeAfter] 耗时302 [MethodInterceptor] 耗时301 [AfterReturning] 无法获取开始时间 执行 login 方法✅ 一眼就能验证B 是错误的