
自定义注解 和 Aop 实现接口耗时计算
Spring-Boot-Aop实现接口耗时计算
Spring中一个重要的点就是面向切面编程,即AOP,可以实现程序中功能的解耦,让一些类共享相同的行为动作。Spring中AOP的实现主要通过JDK的动态代理和CGLIB实现。
AOP:即 在不修改源代码的情况下对代码进行增强。
一、AOP通知(增强)类型
-
before(前置通知): 在方法开始执行前执行
-
after(后置通知): 在方法执行后执行
-
afterReturning(返回后通知): 在方法返回后执行
-
afterThrowing(异常通知): 在抛出异常时执行
-
around(环绕通知): 在方法执行前和执行后都会执行
执行顺序:
around > before > around > after > afterReturning
二、使用自定义注解 和 Aop 实现接口耗时计算(环绕通知)
-
引入依赖
-
<!--Aop--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </dependency>
-
创建自定义注解
-
package com.itcast.commons.annotation; import java.lang.annotation.*; /** * @ClassName: MonitorExecTime * @author: anqin * @Description: 监控执行时间 * @date: 2023/1/27 21:04 */ @Target({ElementType.METHOD}) @Retention(value = RetentionPolicy.RUNTIME) @Documented public @interface MonitorExecTime { String description() default ""; }
-
创建切面类
-
package com.itcast.system; import com.itcast.commons.annotation.MonitorExecTime; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.lang.reflect.Method; /** * @ClassName: RunningTimeAspect * @author: anqin * @Description: 接口运行时间计算 * @date: 2023/1/27 20:21 */ @Slf4j @Aspect @Component @Order(1) public class RunningTimeAspect { /** * 接口耗时超过设置打印耗时信息 - 100 ms */ private static final Long API_EXEC_TIME_PRINT_START = 100L; /** * 接口耗时超过设置发送监控通知 - 3000 ms **/ private static final Long API_EXEC_TIME_MONITOR_START = 3000L; @Around(value = "@annotation(com.itcast.commons.annotation.MonitorExecTime)") public Object interfaceCalculation(ProceedingJoinPoint pj) { // 开始时间 long startTime = System.currentTimeMillis(); // 获取 连接点签名 Signature signature = pj.getSignature(); if (!(signature instanceof MethodSignature)) { return this.proceed(pj); } MethodSignature methodSignature = (MethodSignature) signature; // 获取 通知的方法 Method method = methodSignature.getMethod(); // 切入方法 的 全类名 String name = methodSignature.getDeclaringTypeName() + "." + methodSignature.getName(); // 获取注解描述 MonitorExecTime annotation = method.getAnnotation(MonitorExecTime.class); String description = annotation.description(); try { return this.proceed(pj); } finally { this.computationalConsumptionTime(startTime, name, description); } } /** * 消耗时间计算 */ private void computationalConsumptionTime(Long startTime, String canonicalName, String description) { long consumptionTime = System.currentTimeMillis() - startTime; String template = "%s -- %s -- 耗时%d ms"; String printInfo = String.format(template, description,canonicalName,consumptionTime); log.info(printInfo); } private Object proceed(ProceedingJoinPoint pj) { try { return pj.proceed(pj.getArgs()); } catch (Throwable e) { throw new RuntimeException(e); } } }
-
结果
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果