目录

文章目录

  • 目录
  • AOP的核心概念
  • 模拟aspect advice的执行过程
  • 同一aspect,不同advice的执行顺序
  • 不同aspect,advice的执行顺序
  • 同一aspect,相同advice的执行顺序
  • Transactional Aspect的优先级

AOP的核心概念

要完全理解Spring AOP首先要理解AOP的核心概念和术语,这些术语并不是Spring指定的,而且很不幸,这些术语并不能直观理解,但是,如果Spring使用自己的术语,那将更加令人困惑。

  • Aspect:切面,由一系列切点、增强和引入组成的模块对象,可定义优先级,从而影响增强和引入的执行顺序。事务管理(Transaction management)在java企业应用中就是一个很好的切面样例。
  • Join point:接入点,程序执行期的一个点,例如方法执行、类初始化、异常处理。 在Spring AOP中,接入点始终表示方法执行。
  • Advice:增强,切面在特定接入点的执行动作,包括 “around,” “before” and "after"等多种类型。包含Spring在内的许多AOP框架,通常会使用拦截器来实现增强,围绕着接入点维护着一个拦截器链。
  • Pointcut:切点,用来匹配特定接入点的谓词(表达式),增强将会与切点表达式产生关联,并运行在任何切点匹配到的接入点上。通过切点表达式匹配接入点是AOP的核心,Spring默认使用AspectJ的切点表达式。
  • Introduction:引入,为某个type声明额外的方法和字段。Spring AOP允许你引入任何接口以及它的默认实现到被增强对象上。
  • Target object:目标对象,被一个或多个切面增强的对象。也叫作被增强对象。既然Spring AOP使用运行时代理(runtime proxies),那么目标对象就总是代理对象。
  • AOP proxy:AOP代理,为了实现切面功能一个对象会被AOP框架创建出来。在Spring框架中AOP代理的默认方式是:有接口,就使用基于接口的JDK动态代理,否则使用基于类的CGLIB动态代理。但是我们可以通过设置proxy-target-class="true",完全使用CGLIB动态代理。
  • Weaving:织入,将一个或多个切面与类或对象链接在一起创建一个被增强对象。织入能发生在编译时 (compile time )(使用AspectJ编译器),加载时(load time),或运行时(runtime) 。Spring AOP默认就是运行时织入,可以通过枚举AdviceMode来设置。

模拟aspect advice的执行过程

在这里我们不再展示测试代码,而是通过简单的代码来模拟aspect advice的执行过程

尽管Spring AOP是通过动态代理来实现的,但是我们可以绕过代理,直接模拟出它的执行过程,示例代码:

package doubt;
public class AspectAdviceInvokeProcess {public static void main(String[] args){try {//正常执行AspectInvokeProcess(false);System.out.println("=====分割线=====");//异常执行AspectInvokeProcess(true);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}/*** 切面执行过程* @param isException* @throws Exception*/public static void AspectInvokeProcess(boolean isException) throws Exception{try {try {aroundAdvice(isException);} finally {afterAdvice();}afterReturningAdvice();return;} catch (Exception e) {afterThrowingAdvice(e);throw e;return;}   }/*** 环绕增强* @param isException* @throws Exception*/private static void aroundAdvice(boolean isException) throws Exception {System.out.println("around before advice");try {JoinPoint_Proceed(isException);} finally {System.out.println("around after advice");}}/*** 编织后的接入点执行过程* @param isException*/public static void JoinPoint_Proceed(boolean isException){beforeAdvice();targetMethod(isException);}/*** 前置增强*/private static void beforeAdvice() {System.out.println("before advice");}/*** 目标方法* @param isException*/private static void targetMethod(boolean isException) {System.out.println("target method 执行");if(isException)throw new RuntimeException("异常发生");}/*** 后置增强*/private static void afterAdvice() {System.out.println("after advice");}/*** 正常返回增强*/private static void afterReturningAdvice() {System.out.println("afterReturning");}/*** 异常返回增强* @param e* @throws Exception*/private static void afterThrowingAdvice(Exception e) throws Exception {System.out.println("afterThrowing:"+e.getMessage());}
}

同一aspect,不同advice的执行顺序

上述代码的执行结果,直接体现了同一apsect中不同advice的执行顺序,结果如下:

around before advice
before advice
target method 执行
around after advice
after advice
afterReturning
===============分割线==============
around before advice
before advice
target method 执行
around after advice
after advice
afterThrowing:异常发生
java.lang.RuntimeException: 异常发生

得出结论:


不同aspect,advice的执行顺序

详情可见,《Spring官方文档》
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-ataspectj-advice-ordering

Spring AOP通过指定aspect的优先级,来控制不同aspect,advice的执行顺序,有两种方式:

  • Aspect 类添加注解:org.springframework.core.annotation.Order,使用注解value属性指定优先级。

  • Aspect 类实现接口:org.springframework.core.Ordered,实现 Ordered 接口的 getOrder() 方法。

其中,数值越低,表明优先级越高,@Order 默认为最低优先级,即最大数值:

    /*** Useful constant for the lowest precedence value.* @see java.lang.Integer#MAX_VALUE*/int LOWEST_PRECEDENCE = Integer.MAX_VALUE;

最终,不同aspect,advice的执行顺序

  • 入操作(Around(接入点执行前)、Before),优先级越高,越先执行;
  • 一个切面的入操作执行完,才轮到下一切面,所有切面入操作执行完,才开始执行接入点;
  • 出操作(Around(接入点执行后)、After、AfterReturning、AfterThrowing),优先级越低,越先执行。
  • 一个切面的出操作执行完,才轮到下一切面,直到返回到调用点;

如下图所示:

先入后出,后入先出


同一aspect,相同advice的执行顺序

同一aspect,相同advice的执行顺序并不能直接确定,而且 @Orderadvice方法上也无效,但是有如下两种变通方式:

  • 将两个 advice 合并为一个 advice,那么执行顺序就可以通过代码控制了
  • 将两个 advice 分别抽离到各自的 aspect 内,然后为 aspect 指定执行顺序

Transactional Aspect的优先级

Spring事务管理(Transaction Management),也是基于Spring AOP。

在Spring AOP的使用中,有时我们必须明确自定义aspect的优先级低于或高于事务切面(Transaction Aspect),所以我们需要知道:

  • 事务切面优先级:默认为最低优先级
LOWEST_PRECEDENCE = Integer.MAX_VALUE
  • 事务的增强类型:Around advice,其实不难理解,进入方法开启事务,退出方法提交或回滚,所以需要环绕增强。
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport implements DisposableBean {protected AbstractTransactionAspect(TransactionAttributeSource tas) {setTransactionAttributeSource(tas);}@SuppressAjWarnings("adviceDidNotMatch")Object around(final Object txObject): transactionalMethodExecution(txObject) {MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();// Adapt to TransactionAspectSupport's invokeWithinTransaction...try {return invokeWithinTransaction(methodSignature.getMethod(), txObject.getClass(), new InvocationCallback() {public Object proceedWithInvocation() throws Throwable {return proceed(txObject);}});}catch (RuntimeException ex) {throw ex;}catch (Error err) {throw err;}catch (Throwable thr) {Rethrower.rethrow(thr);throw new IllegalStateException("Should never get here", thr);}}
}
  • 如何修改事务切面的优先级:
    在开启事务时,通过设置 @EnableTransactionManagement<tx:annotation-driven/> 中的, order 属性来修改事务切面的优先级。
    详情可见,《Spring官方文档》https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#tx-annotation-driven-settings

关注作者公众号,随时了解更多干货!


往期推荐


  • 解决Java开发中使用POI读写Excel时面对的两个麻烦
  • 从简历被拒到收割今日头条offer,我花了一年时间
  • Redis之坑:完全理解Redis事务
  • 完全理解TCP/UDP、HTTP长连接、Websocket、SockJS/Socket.IO以及STOMP的区别和联系(改)
  • Nginx之坑:完全理解location中的index,配置网站初始页(改)
  • 安全(一)— 完全理解RSA加密算法
  • Spring AOP之坑:完全搞清楚advice的执行顺序

Spring AOP之坑:完全搞清楚advice的执行顺序相关推荐

  1. Spring AOP:搞清楚advice的执行顺序

    文章目录 目录 AOP的核心概念 模拟aspect advice的执行过程 同一aspect,不同advice的执行顺序 不同aspect,advice的执行顺序 同一aspect,相同advice的 ...

  2. Spring关于AOP中关于advice的执行顺序

    AOP的核心概念 要完全理解Spring AOP首先要理解AOP的核心概念和术语,这些术语并不是Spring指定的,而且很不幸,这些术语并不能直观理解,但是,如果Spring使用自己的术语,那将更加令 ...

  3. 【Spring Boot入门】AOP基础及Advice的执行顺序

    本文主要分为两个部分,首先介绍AOP的基础,包括为什么要使用AOP以及AOP中的基本概念,然后讲解AOP中各类Advice的执行顺序并给出简单示例. 一.AOP基础 1.为什么要使用AOP AOP(A ...

  4. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

  5. Spring AOP源码解析-拦截器链的执行过程

    一.简介 在前面的两篇文章中,分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在得到了 bean 的代理对象,且通知也以合适的方式插在了目标方 ...

  6. spring 基于XML的申明式AspectJ通知的执行顺序

    spring 基于XML的申明式AspectJ通知的执行顺序 关于各种通知的执行顺序,结论:与配置文件中的申明顺序有关 1. XML文件配置说明 图片来源:<Java EE企业级应用开发教程&g ...

  7. 一个Spring AOP的坑!很多人都犯过!

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 很多读者看完之后表示用起来很爽,但是后台也有人留言说自己配 ...

  8. Spring AOP 之 多切面

    接着上文:https://blog.csdn.net/single_wolf_wolf/article/details/81772837 多切面 相对来说,只是定义多个切面类,同时配置类中设置一下, ...

  9. Spring AOP示例教程 - Aspect,Advice,Pointcut,JoinPoint,Annotations,XML Configuration

    Spring AOP示例教程 - Aspect,Advice,Pointcut,JoinPoint,Annotations,XML Configuration Spring Framework是基于两 ...

最新文章

  1. oracle update批量修改sql语句编写
  2. Java之定时任务详解
  3. Facebook首席工程负责人胡鲁辉:数字化2.0的理念、架构与业务模型丨鲸犀峰会
  4. table { border-collapse:collapse; }
  5. mysql 5.6 初始化_MySQL 5.6 关于登陆的初始化设置
  6. 11个步骤完美排查Linux机器是否已经被入侵
  7. C# 读写ACCESS的OLE对象,演示图片与长文件的读写
  8. 《Python Cookbook 3rd》笔记(2.13):字符串对齐
  9. 2.Redis数据操作
  10. bat批处理教程 24
  11. html中在线预览pdf文件之pdf在线预览插件
  12. 操作系统 第五章 IO管理
  13. ReportServer中,要配置远程可登录帐号
  14. h5手机端浏览器机制_h5浏览器缓存机制
  15. python的类,复现assert和eval成功失败原因
  16. 【蓝桥杯选拔赛真题30】Scratch小猫奔跑 少儿编程scratch蓝桥杯选拔赛真题讲解
  17. 腾讯往届笔试面试题整理大全
  18. 查看苹果审核反馈的crash日志/崩溃日志
  19. layui分页样式改变
  20. 【九阳真经口诀】他强由他强,清风拂山岗;他横由他横,明月照大江。他自狠来他自恶,我自一口真气足。

热门文章

  1. 计算机房显示屏无信号,显示屏无信号,教您电脑显示屏无信号怎么办
  2. 铜仁一中2021高考成绩查询,贵州铜仁第一中学2021年招生录取分数线
  3. MAC 安装flutter环境
  4. ORACLE- check 检查约束
  5. NEXUS 上传到私仓的SNAPSHOT 包下载不下来
  6. 优秀好用的Mac平台上的DRM音频转换辅助工具
  7. 【论文精度】Subdivision-Based Mesh Convolution Networks
  8. 自然语言处理之数据平滑方法
  9. 第29节 防火墙部署实验(IP、策略、NAT、HA)——基于topgate防火墙的网页部署方法
  10. 使用三层思想完成商品管理系统