美文网首页
Springboot整合AOP和注解,实现丰富的切面功能

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

作者: 南瓜慢说 | 来源:发表于2023-02-07 10:47 被阅读0次

    简介

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

    整合过程

    首先创建一个注解:

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface PkslowLogTime {
    }
    

    然后在一个Service中使用注解:

    @Service
    @Slf4j
    public class TestService {
        @PkslowLogTime
        public void fetchData() {
            log.info("fetchData");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
    

    这个Service的方法会在Controller中调用:

    @GetMapping("/hello")
    public String hello() {
      log.info("------hello() start---");
      test();
      staticTest();
      testService.fetchData();
      log.info("------hello() end---");
      return "Hello, pkslow.";
    }
    

    接着是关键一步,我们要实现切面,来找到注解并实现对应功能:

    @Aspect
    @Component
    @Slf4j
    public class PkslowLogTimeAspect {
        @Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")
        public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
            log.info("------PkslowLogTime doAround start------");
            MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
    
            // Get intercepted method details
            String className = methodSignature.getDeclaringType().getSimpleName();
            String methodName = methodSignature.getName();
    
            // Measure method execution time
            StopWatch stopWatch = new StopWatch(className + "->" + methodName);
            stopWatch.start(methodName);
            Object result = joinPoint.proceed();
            stopWatch.stop();
            // Log method execution time
            log.info(stopWatch.prettyPrint());
            log.info("------PkslowLogTime doAround end------");
            return result;
        }
    }
    

    @Around("@annotation(com.pkslow.springboot.aop.PkslowLogTime) && execution(* *(..))")这个表达式很关键,如果不对,将无法正确识别;还有可能出现多次调用的情况。多次调用的情况可以参考:Stackoverflow

    这里使用了Spring的StopWatch来计时。

    测试

    通过maven build包:

    $ mvn clean package
    

    日志可以看到有对应的织入信息:

    [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))
    [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))
    [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))
    [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))
    [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))
    [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))
    [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

    相关文章

      网友评论

          本文标题:Springboot整合AOP和注解,实现丰富的切面功能

          本文链接:https://www.haomeiwen.com/subject/piwxkdtx.html