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 四个通知模块,启动会报错
写的不好或总结的不好望多多见谅,有错误请指出,免得误人子弟;
SpringBoot2.x中的AOP机制总结(附带demo)的更多相关文章
- 理解Django 中Call Stack 机制的小Demo
1.工作流程 request/response模式下,request并不是直接到达view方法,view方法也不是将返回的response直接发送给浏览器的,而是request由外到里的层层通过各种m ...
- Castle框架中的IOC和AOP机制
反转控制(IOC)和面向切面编程(AOP)技术作为当前比较流行的技术,其优势已受到广泛关注,但是这两项新技术在实际项目上的应用研究却很落后,而且在.NET平台下实现这两项技术没有形成可以广泛套用的框架 ...
- SpringBoot2.0中的事务@Transactional
在SpringBoot2.0中使用使用需要注意的地方. 1. 加@Transactional的方法不能是private和protected修饰,private会直接报编译错误,protected不会报 ...
- .Net中的AOP系列之《拦截位置》
返回<.Net中的AOP>系列学习总目录 本篇目录 位置拦截 .Net中的字段和属性 PostSharp位置拦截 真实案例--懒加载 .Net中的懒加载 使用AOP实现懒加载 如何懒加载字 ...
- 浅谈Linux中的信号处理机制(二)
首先谢谢 @小尧弟 这位朋友对我昨天夜里写的一篇<浅谈Linux中的信号处理机制(一)>的指正,之前的题目我用的“浅析”一词,给人一种要剖析内核的感觉.本人自知功力不够,尚且不能对着Lin ...
- 【转】在.Net中关于AOP的实现
原文地址:http://www.uml.org.cn/net/201004213.asp 一.AOP实现初步 AOP将软件系统分为两个部分:核心关注点和横切关注点.核心关注点更多的是Domain Lo ...
- [Spring-AOP-XML] 利用Spirng中的AOP和XML进行事务管理
Spring中的AOP进行事务管理有三种方式 A.自定义事务切面 利用AspectJ来编写事务,我们一般把这个切面作用在service层中.其他代码在下面 编写一个Transaction实现类,通过S ...
- Spring框架中的AOP技术----配置文件方式
1.AOP概述 AOP技术即Aspect Oriented Programming的缩写,译为面向切面编程.AOP是OOP的一种延续,利用AOP技术可以对业务逻辑的各个部分进行隔离,从使得业务逻辑各部 ...
- 【Java基础】java中的反射机制与动态代理
一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...
随机推荐
- Cisco的互联网络操作系统IOS和安全设备管理器SDM__管理Cisco互联网络
1.如果不能远程登录到一台设备上,可能是由于远程设备上没有设置口令.也可能是由于访问控制列表过滤了远程登录会话. show users:检查都有哪些设备连接到了此路由器. clear line #:清 ...
- 利用PWM脉宽调制实现呼吸灯
1.设计目标 完成一个呼吸灯,从亮到灭的时间为2秒,从灭到亮的时间为2秒,以此不断往复. 2.设计步骤 2.1设计分析 利用PWM(脉冲宽度调制)实现led灯亮度的变化,只需要改变占空比就可以实现,具 ...
- 如何用RabbitMQ实现延迟队列
前言 在 jdk 的 juc 工具包中,提供了一种延迟队列 DelayQueue.延迟队列用处非常广泛,比如我们最常见的场景就是在网购或者外卖平台中发起一个订单,如果不付款,一般 15 分钟后就会被关 ...
- jackson学习之七:常用Field注解
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- 图的连通性——Tarjan算法&割边&割点
tarjan算法 原理: 我们考虑 DFS 搜索树与强连通分量之间的关系. 如果结点 是某个强连通分量在搜索树中遇到的第⼀个结点,那么这个强连通分量的其余结点肯定 是在搜索树中以 为根的⼦树中. 被称 ...
- Codeforces Round #650 (Div. 3) A. Short Substrings
题目链接:https://codeforces.com/contest/1367/problem/A 题意 给出一个字符串 $t$,找出原字符串 $s$,$t$ 由 $s$ 从左至右的所有长为 $2$ ...
- Best Reward && Girls' research
After an uphill battle, General Li won a great victory. Now the head of state decide to reward him w ...
- UVA-11019 二维哈希算法
UVA-11019 题意: 就是给你AB两个字符矩阵,问你B矩阵在A矩阵中的出现次数. 题解: 参考链接:https://blog.csdn.net/qq_38891827/java/article ...
- Codeforces Round #550 (Div. 3) E. Median String (思维,模拟)
题意:给你两个字符串\(s\)和\(t\),保证\(t\)的字典序大于\(s\),求他们字典序中间的字符串. 题解:我们假设题目给的不是字符串,而是两个10禁止的正整数,那么输出他们之间的数只要把他两 ...
- std::invoke_result的实现详解
目录 目录 前言 invoke_result 标准库中的invoke_result 我的实现 后记 前言 本篇博文将详细介绍一下libstdc++中std::invoke_result的实现过程,由于 ...