上篇文章说到使用原生的StopWatch查看程序执行时间,本文将介绍使用注解+AOP(面向切面编程)的方式实现其功能,一来可以快速使用StopWatch功能,二来让大家熟悉一下如何使用注解进行切面编程
1. 自定义一个注解 StopWatchTime
@Retention(RetentionPolicy.RUNTIME)
@Target({METHOD})
public @interface StopWatchTime {
String value() default "";
}复制代码
本注解主要用在方法上,故target为METHOD,并设定一个value,可用于定义此次观察的名称。
2. 创建切面类
- 引用AOP支持包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>复制代码
- 创建切面类
@Aspect // 1
@Component // 2
public class StopWatchTimeAdvice {
@Around("@annotation(stopWatchTime)") // 3
public Object invoke(ProceedingJoinPoint thisJoinPoint, StopWatchTime stopWatchTime) throws Throwable {
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
String name = StringUtils.isEmpty(stopWatchTime.value()) ? methodSignature.getName() : stopWatchTime.value(); // 4
StopWatch stopWatch = new StopWatch(name);
stopWatch.start("00");
Object object = thisJoinPoint.proceed(); // 5
stopWatch.stop();
System.err.println(stopWatch.prettyPrint()); // 6
return object;
}
}复制代码
代码解释
- 通过@Aspect 注解声明一个切面
- 通过@Component 让此切面成为Spring容器管理的Bean
- 通过@Around注解声明一个建言,并使用定义了自定义注解@StopWatchTime的方法作为切入点
- 获取注解上的属性,如果无就默认当前的方法名“ methodSignature.getName() ”
- 作好StopWatch的前期准备后,执行切入点的方法体
- 执行完成后打印执行结果
3. 注解被观察方法
@StopWatchTime
public void run(String... strings) throws Exception {
step1();
step2();
step3();
}
private void step1() throws InterruptedException {
Thread.sleep(100L);
}
private void step2() throws InterruptedException {
Thread.sleep(850L);
}
private void step3() throws InterruptedException {
Thread.sleep(2000L);
}复制代码
只要@StopWatchTime写在哪个方法上就能监控得出哪个方法的执行时间,但且限于public非静态方法
输出结果
StopWatch 'run': running time (millis) = 2985 ----------------------------------------- ms % Task name ----------------------------------------- 02985 100% 00
大家可能会看出来,此方法虽然使用起来方便,但只能显示单个方法的执行时间,下一篇将告诉大家如何使用AOP的方法扩展出可同时观察一个代码段里多个方法的执行情况,敬请期待。