Springboot整合AOP和注解,实现丰富的切面功能

[复制链接]
发表于 2023-2-8 11:02:51 | 显示全部楼层 |阅读模式
简介

我们在文章《Spring AOP与AspectJ的对比及应用》介绍了AOP的使用,这篇文章讲解一下AOP与注解的整合,通过注解来使用AOP,会非常方便。为了简便,我们还是来实现一个计时的功能
整合过程

首先创建一个注解:
  1. @Retention(RetentionPolicy.RUNTIME)
  2. @Target(ElementType.METHOD)
  3. public @interface PkslowLogTime {
  4. }
复制代码
然后在一个Service中使用注解:
  1. @Service
  2. @Slf4j
  3. public class TestService {
  4.     @PkslowLogTime
  5.     public void fetchData() {
  6.         log.info("fetchData");
  7.         try {
  8.             Thread.sleep(500);
  9.         } catch (InterruptedException e) {
  10.             throw new RuntimeException(e);
  11.         }
  12.     }
  13. }
复制代码
这个Service的方法会在Controller中调用:
  1. @GetMapping("/hello")
  2. public String hello() {
  3.   log.info("------hello() start---");
  4.   test();
  5.   staticTest();
  6.   testService.fetchData();
  7.   log.info("------hello() end---");
  8.   return "Hello, pkslow.";
  9. }
复制代码
接着是关键一步,我们要实现切面,来找到注解并实现对应功能
  1. @Aspect
  2. @Component
  3. @Slf4j
  4. public class PkslowLogTimeAspect {
  5.     @Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")
  6.     public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
  7.         log.info("------PkslowLogTime doAround start------");
  8.         MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
  9.         // Get intercepted method details
  10.         String className = methodSignature.getDeclaringType().getSimpleName();
  11.         String methodName = methodSignature.getName();
  12.         // Measure method execution time
  13.         StopWatch stopWatch = new StopWatch(className + "->" + methodName);
  14.         stopWatch.start(methodName);
  15.         Object result = joinPoint.proceed();
  16.         stopWatch.stop();
  17.         // Log method execution time
  18.         log.info(stopWatch.prettyPrint());
  19.         log.info("------PkslowLogTime doAround end------");
  20.         return result;
  21.     }
  22. }
复制代码
@Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")这个表达式很关键,如果不对,将无法正确识别;还有可能出现多次调用的情况。多次调用的情况可以参考:Stackoverflow
这里使用了Spring的StopWatch来计时。
测试

通过maven build包:
  1. $ mvn clean package
复制代码
日志日志可以看到有对应的织入信息:
  1. [INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
  2. [INFO] Join point 'method-execution(java.lang.String com.pkslow.springboot.controller.TestController.hello())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:22) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
  3. [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:31) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
  4. [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.test())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:31) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
  5. [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:37) advised by around advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
  6. [INFO] Join point 'method-execution(void com.pkslow.springboot.controller.TestController.staticTest())' in Type 'com.pkslow.springboot.controller.TestController' (TestController.java:37) advised by before advice from 'com.pkslow.springboot.aop.ControllerAspect' (ControllerAspect.class(from ControllerAspect.java))
  7. [INFO] Join point 'method-execution(void com.pkslow.springboot.service.TestService.fetchData())' in Type 'com.pkslow.springboot.service.TestService' (TestService.java:12) advised by around advice from 'com.pkslow.springboot.aop.PkslowLogTimeAspect' (PkslowLogTimeAspect.class(from PkslowLogTimeAspect.java))
复制代码
启动应用后访问接口,日志日志如下:

总结

通过注解可以实现很多功能,也非常方便。而且注解还可以添加参数,组合使用更完美了。
代码请看GitHub: https://github.com/LarryDpk/pkslow-samples

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表