zoukankan      html  css  js  c++  java
  • SpringBoot2.x中的AOP机制总结(附带demo)

    寄语:刚开始学aop的时候是大三吧,老师讲的不好,我也没学好,导致现在才有个较为清晰的认知,那个时候只知道有aop,

    根部不明白aop的作用,时至今日,任然觉得aop难以咀嚼,奈何平时不用面试要用,特此总结。

    下面开始总结:

    注意:我使用的是springboot2.1+maven3.6,请自行搭建基础环境

    项目github地址:https://github.com/zgq7/devloper-mine/blob/master/src/main/java/com/dev/config/aop/BaseAop.java

    1:导入maven依赖

    <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-aop -->
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
    <version>2.1.6.RELEASE</version>
    </dependency>

    2:创建一个class作为切面类,如下:

    package com.dev.config.aop;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.core.annotation.Order;
    
    import java.util.Collections;
    
    /**
     * Created by zgq7 on 2019/7/12.
    * * 各通知执行顺序: * 1:around-> * 2:before-> * 3:around->retrun code -> * 4:after-> * 5:afterReturning-> * 6:afterThrowing * </p> * <p> * order 执行顺序: * 1:进入目的方法时:order值越小越先执行 * 2:从目的方法出去时:order值越大越先执行 * </p>
    */ @Aspect @Order(1) public class BaseAop { private final Logger log = LoggerFactory.getLogger(this.getClass()); /** * 写入具体切面点 * * @apiNote execution 路径中的 "." 如果是精确到类,则一个就行,如果是精确到包就得两个 "." * @apiNote execution 路径若只精确到包,就无法使用 before、after、afterReturuning、around 四个通知模块,启动会报错 **/ @Pointcut("execution(public * com.dev.controller.TestController.s())") public void aspect() { } /** * 进入方法体前 **/ @Before(value = "aspect()") public void before(JoinPoint joinPoint) { log.info("before :参数类型:{}", joinPoint.getArgs()); } /** * 该切面返回数据前(在retrun之前执行) **/ @After(value = "aspect()") public void after(JoinPoint joinPoint) { log.info("aop before return :{}", joinPoint.toLongString()); } /** * 该切面返回数据后 * joinPoint.getSignature() 返回方法放回类型 及 方法路径 **/ @AfterReturning(value = "aspect()", returning = "result") public void afterReturning(Object result) { log.info("aop after return :返回结果:{}", result); } /** * 环绕通知 * 1:before之前 * 2:afterReturning之后 * * @apiNote 1:@Around 下接的方法的参数必须为 ProceedingJoinPoint 类型, * @apiNote 2:proceedingJoinPoint.proceed() 产生的结果即为 @AfterReturning 中的 result,可 debug 调试 * @apiNote 3:由于@Around要提前获取到目的方法的执行结果,且@Around提前于@AfterThrowing运行,因此异常将在@Around中被捕获,从而导致@AfterThrowing捕获不到异常,因此@Around与@AfterThrowing混合使用 **/ //@Around(value = "aspect()") public Object around(ProceedingJoinPoint proceedingJoinPoint) { log.info("aop arrounding :{}", proceedingJoinPoint.getSignature().getName()); try { return proceedingJoinPoint.proceed(); } catch (Throwable throwable) { log.info("aop arrounding error :{}", throwable.getMessage()); //throwable.printStackTrace(); return Collections.EMPTY_MAP; } } /** * 切面报错 **/ @AfterThrowing(value = "aspect()", throwing = "exception") public void afterThrowing(Throwable exception) { log.error("exception occured , msg : {}", exception.getMessage()); if (exception instanceof NullPointerException) log.info("空指针异常"); } }

    notice2.1:多个aspect的执行顺序

      1:进入目的方法时:order值越小越先执行

      2:从目的方法出去时:order值越大越先执行

    notice2.2:aspect 中 @befer、@after、@afterReturning、@around、@afterThrowing的执行顺序

     * 1:around->
     * 2:before->
     * 3:around->retrun code ->
     * 4:after->
     * 5:afterReturning
    notice2.2.1:各项通知也严格按照order的值进行传递一层一层的走下去

    notice2.3:aspect 中@around 下属的方法必须要有返回值,否则就是一个 “有问题” 的切面

     * @apiNote 1:@Around 下接的方法的参数必须为 ProceedingJoinPoint 类型,
     * @apiNote 2:proceedingJoinPoint.proceed() 产生的结果即为  @AfterReturning 中的 result,可 debug 调试

    notice2.4:aspect 中@around 不能与 @afterThrowing 混用

     * @apiNote 3:由于@Around要提前获取到目的方法的执行结果,且@Around提前于@AfterThrowing运行,因此异常将在@Around中被捕获,从而导致@AfterThrowing捕获不到异常,因此@Around与@AfterThrowing混合使用

    notice2.5:aspect 中@PointCut中的execution类路径或者包路径问题

     * @apiNote execution 路径中的 "." 如果是精确到类,则一个就行,如果是精确到包就得两个 "."
     * @apiNote execution 路径若只精确到包,就无法使用 before、after、afterReturuning、around 四个通知模块,启动会报错










    写的不好或总结的不好望多多见谅,有错误请指出,免得误人子弟;


    
    
    
  • 相关阅读:
    - viewDidLoad 和
    C#实现excel导入到sql server 2008(.net版)
    Windows PE 第十章 加载配置信息
    Windows PE第九章 线程局部存储
    Windows PE第九章 线程局部存储
    Windows PE 第八章 延迟加载导入表
    Windows PE 第八章 延迟加载导入表
    Windows PE资源表编程(枚举资源树)
    Windows PE资源表编程(枚举资源树)
    欺骗的艺术-读后总结
  • 原文地址:https://www.cnblogs.com/zgq7/p/11310142.html
Copyright © 2011-2022 走看看