AOP(面向切面编程)是一种编程范式,允许我们将横切关注点(如日志记录、事务管理、安全等)从业务逻辑中分离出来。下面是一个简单的手写AOP示例,展示了如何在Java中实现AOP功能。
导入依赖
1 2 3 4 5
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> <version>3.4.8</version> </dependency>
|
定义自定义注解
1 2 3 4 5 6 7
| @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface TimeMonitor { String value() default "";
long slowTime() default 1000; }
|
定义切面
@annotation(cn.sowink.aopdemo.aop.TimeMonitor):拦截所有被 @TimeMonitor 注解标记的方法,并用环绕通知包裹它们
需要明确注解的完整包路径,以确保切面能够正确识别和拦截目标方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| @Component @Aspect @Slf4j public class ExecutionTimeAspect {
@Around("@annotation(cn.sowink.aopdemo.aop.TimeMonitor)") public Object monitorTime(ProceedingJoinPoint pjp) throws Throwable { long startTime = System.currentTimeMillis();
try { return pjp.proceed(); } finally { long endTime = System.currentTimeMillis(); long executionTime = endTime - startTime;
MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); String className = signature.getClass().getName(); String methodName = method.getName();
TimeMonitor annotation = method.getAnnotation(TimeMonitor.class); long slowTime = annotation != null ? annotation.slowTime() : 1000; if (executionTime > slowTime) { log.info("方法 {}.{} 执行时间 {} ms,超过慢执行时间阈值 {} ms", className, methodName, executionTime, slowTime); } else { log.info("方法 {}.{} 执行时间 {} ms", className, methodName, executionTime); } } } }
|
使用示例
1 2 3 4 5 6 7 8
| @Service public class OrderService {
@TimeMonitor("简单计算") public void calculate(int a, int b) { System.out.println("正在计算..."); } }
|
输出
1 2
| 正在计算... 2026-04-08T21:30:54.661+08:00 INFO 17587 --- [AOPDemo] [ main] c.s.aopdemo.aspect.ExecutionTimeAspect : 方法 org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint$MethodSignatureImpl.calculate 执行时间 0 ms
|