Before、AfterReturning、AfterThrowing、After、Around
不管配置哪种Advice,都需要指定2个属性:
- method:指定将哪个方法转换成Advice。
- pointcut或pointcut-ref:pointcut直接指定切入点表达式;pointcut-ref引入已有的切入点表达式。
Before:在目标执行之前织入的Advice。
AfterReturning:在目标方法成功完成之后织入的Advice
可额外指定一个returning属性,该属性值有2个作用:
Advice方法可通过该属性指定的值来访问目标方法的返回值。
Advice方法声明该返回值类型时,限制目标方法的返回值必须是指定的类型。否则该Advice不会织入。如果不想对目标方法的返回值进行限制,可将该返回值声明为Object。
AfterThrowing:在目标方法出现异常时织入的Advice。这种Advice类似于catch块。
可额外指定一个throwing属性,该属性值有2个作用:
Advice方法可通过该属性指定的值来访问目标方法抛出的异常。
Advice方法声明该异常类型时,限制目标方法的抛出的异常必须是指定的类型。否则该Advice不会织入。如果不想对目标方法抛出的异常进行限制,可将该异常声明为Exception或Throwable。
After:不管目标方法成功完成,还是异常结束,该Advice都会织入。这种Advice类似于finally块。(可以用来释放资源)
Around:这种Advice功能最强大,它既可以访问、修改目标方法调用参数,也可访问、修改目标方法的返回值。它甚至完全阻止目标方法的执行。它既可在目标方法之前织入,也可在目标方法之后织入。它是线程不安全,能用其他Advice搞定的,就不要把Around Advice拿出来。
Around Advice方法必须满足以下3点:
- 必须声明返回值类型。
- 必须声明一个类型为org.aspectj.lang.ProceedingJoinPoint类型的形参。
- 必须调用ProceedingJoinPoint形参的proceed()方法,这就是回调目标方法。如果没有这一行,目标方法不会执行。
package com.lwy.aspect;
import org.aspectj.lang.ProceedingJoinPoint;
public class AroundAdviceAspect {
public Object around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("模拟开启事务");
/**
* ProceedingJoinPoint继承了JoinPoint,JoinPoint包含了如下方法:
* getArgs:获取目标方法调用参数
* getKind:获取连接点类型
* getSignature:获取目标方法的方法签名
* getTarget:获取目标对象
* getThis:获取AOP代理
*/
//访问到目标方法的调用参数
Object[] args = pjp.getArgs();
// ------------------以上在目标方法之前织入------------------
// 回到原来的目标方法,如果去掉此行,目标方法就不会执行
Object returnObject = pjp.proceed(args);
// ------------------以下在目标方法之前织入------------------
System.out.println("模拟关闭事务");
return returnObject;
}
}
五种Advice的功能总结:
| Before | AfterReturning | AfterThrowing | After | Around |
访问调用参数 | Y | Y | Y | Y | Y |
修改调用参数 | N | N | N | N | Y |
阻止目标方法执行 | Y(抛异常) | N | N | N | Y |
访问返回值 | N | Y | N | N | Y |
修改返回值 | N | N | N | N | Y |
AOP的切入点指示符:
Execution([访问权限] [返回值类型] 包.类.方法(形参) [throws 异常])
形参列表:.. 代表任意个任意类型的参数;* 代表1个任意类型的参数
例如:(*,java.lang.String):2个形参,且第二个形参类型为java.lang.String