Spring关于AOP中关于advice的执行顺序
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](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的执行顺序并不能直接确定,而且 @Order 在advice方法上也无效,但是有如下两种变通方式:
将两个 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
详情请看下方两篇(转载):
https://blog.csdn.net/rainbow702/article/details/52185827
https://blog.csdn.net/qq_32331073/article/details/80596084?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
Spring关于AOP中关于advice的执行顺序相关推荐
- 【Spring Boot入门】AOP基础及Advice的执行顺序
本文主要分为两个部分,首先介绍AOP的基础,包括为什么要使用AOP以及AOP中的基本概念,然后讲解AOP中各类Advice的执行顺序并给出简单示例. 一.AOP基础 1.为什么要使用AOP AOP(A ...
- Spring AOP:搞清楚advice的执行顺序
文章目录 目录 AOP的核心概念 模拟aspect advice的执行过程 同一aspect,不同advice的执行顺序 不同aspect,advice的执行顺序 同一aspect,相同advice的 ...
- Spring AOP之坑:完全搞清楚advice的执行顺序
目录 文章目录 目录 AOP的核心概念 模拟aspect advice的执行过程 同一aspect,不同advice的执行顺序 不同aspect,advice的执行顺序 同一aspect,相同advi ...
- python实例化是什么意思_Python中实例化class的执行顺序示例详解
前言 本文主要介绍了关于Python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧 Python里对类的实例化时有怎样的顺序 一般来说一个类里面有类变量和方法,比如我们定 ...
- Spring启动,constructor,@PostConstruct,afterPropertiesSet,onApplicationEvent执行顺序 原创 2016年09月29日 11:39:2
Spring启动,constructor,@PostConstruct,afterPropertiesSet,onApplicationEvent执行顺序 原创 2016年09月29日 11:39:2 ...
- for循环中各语句的执行顺序
for循环中各语句的执行顺序 初学编程的话,基本上是避不开for循环的.而作为一个很基本的知识点,我们就来梳理一下for循环中各语句的执行顺序! 首先我们来介绍一下for循环的基本形式 for(初始化 ...
- ASP.NET 2.0中Page事件的执行顺序
Page 执行中将按照如下顺序激活事件: Page.PreInit Page.Init Page.InitComplite Page.PreLoad Page.Load Page.LoadComple ...
- Java中finally和return执行顺序
思考一个问题 Java异常捕获机制try-catch-finally块中的finally语句是否一定会被执行?起码在以下两种情况下是不会被执行的: 1.在try之前就返回了,try没有执行到. 2.t ...
- SQL语句中各个部分的执行顺序(转)
原文链接:http://www.tuicool.com/articles/fERNv2 写在前面的话:有时不理解SQL语句各个部分执行顺序,导致理解上出现偏差,或者是书写SQL语句时随心所欲,所以有必 ...
最新文章
- HDU 2444 The Accomodation of Students (二部图+染色)
- 网站SEO优化如何讨好搜索引擎蜘蛛?
- 安卓一键新机_安卓福音!微信终于推出这个功能,再也不用羡慕iPhone
- 【基础部分】之apache配置与应用
- qt5使用mysql
- 稀疏矩阵十字链表类java_稀疏矩阵的十字链表存储表示
- RabbiqMQ快速入门
- Java实现邮箱找回密码
- 多行查询结果合并sys_connect_by_path
- python程序扩展名主要有-python文件的后缀名都有哪些?
- 如何在小数点前补0,new DecimalFormat(##0.00);
- linux界面如何进行文档排序,Linux中使用sort对文档中的内容进行排序
- 第五章 多个消费者监听同一个队列
- 2020中青杯B题股指与国家经济数学建模全过程文档及程序
- 存储之磁盘阵列RAID
- 软件生命周期是什么?
- iOS-App移交(更换app开发者账号)
- 百度网盘百度云不限速下载几种方法介绍汇总(借助网页或者软件等)
- 一个清华保送生妈妈对竞赛的感受,自主招生家长都要看看!
- ansible中的加密