要彻底理解Spring AOP首先要理解AOP的核心概念和术语,这些术语并非Spring指定的,并且很不幸,这些术语并不能直观理解,可是,若是Spring使用本身的术语,那将更加使人困惑。html
proxy-target-class="true"
,彻底使用CGLIB动态代理。枚举AdviceMode
来设置。在这里咱们再也不展现测试代码,而是经过简单的代码来模拟aspect advice的执行过程。java
尽管Spring AOP是经过动态代理
来实现的,可是咱们能够绕过代理,直接模拟出它的执行过程,示例代码:spring
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 block
e.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());
}
}
复制代码
上述代码的执行结果,直接体现了同一apsect中不一样advice的
执行顺序,结果以下:bash
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: 异常发生
复制代码
得出结论: 框架
详情可见,《Spring官方文档》 docs.spring.io/spring/docs…测试
Spring AOP经过指定aspect
的优先级,来控制不一样aspect,advice的执行顺序
,有两种方式:this
Aspect 类添加注解:org.springframework.core.annotation.Order,使用注解value
属性指定优先级。spa
Aspect 类实现接口:org.springframework.core.Ordered,实现 Ordered 接口的 getOrder() 方法。代理
其中,数值越低,代表优先级越高,@Order 默认为最低优先级,即最大数值:code
/** * Useful constant for the lowest precedence value. * @see java.lang.Integer#MAX_VALUE */
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
复制代码
最终,不一样aspect,advice的执行顺序
:
以下图所示:
先入后出,后入先出
同一aspect,相同advice的执行顺序
并不能直接肯定,并且 @Order 在advice
方法上也无效,可是有以下两种变通方式:
Spring事务管理(Transaction Management),也是基于Spring AOP。
在Spring AOP的使用中,有时咱们必须明确自定义aspect的优先级低于或高于事务切面(Transaction Aspect),因此咱们须要知道:
LOWEST_PRECEDENCE = Integer.MAX_VALUE
复制代码
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官方文档》docs.spring.io/spring/docs…