1、通知类型
AOP的通知类型共5种
-
前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行
应用:数据校验
-
后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知
应用:现场清理
-
返回后通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
应用:返回值相关数据处理
-
抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
应用:对原始方法中出现的异常信息进行处理
-
环绕通知:在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行
应用:十分强大,可以做任何事情
1.1、aop:before
-
名称:aop:before
-
类型:标签
-
归属:aop:aspect标签
-
作用:设置前置通知
- 格式:
<aop:aspect ref="adviceId">
<aop:before method="methodName" pointcut="……"/>
</aop:aspect>
-
说明:一个aop:aspect标签中可以配置多个aop:before标签
-
基本属性:
-
method :在通知类中设置当前通知类别对应的方法
-
pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
-
pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
-
1.2、aop:after
-
名称:aop:after
-
类型:标签
-
归属:aop:aspect标签
-
作用:设置后置通知
- 格式:
<aop:aspect ref="adviceId">
<aop:after method="methodName" pointcut="……"/>
</aop:aspect> -
说明:一个aop:aspect标签中可以配置多个aop:after标签
-
基本属性:
-
method :在通知类中设置当前通知类别对应的方法
-
pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
-
pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
-
1.3、aop:after-returning
-
名称:aop:after-returning
-
类型:标签
-
归属:aop:aspect标签
-
作用:设置返回后通知
- 格式:
<aop:aspect ref="adviceId">
<aop:after-returning method="methodName" pointcut="……"/>
</aop:aspect>
-
说明:一个aop:aspect标签中可以配置多个aop:after-returning标签
-
基本属性:
-
method :在通知类中设置当前通知类别对应的方法
-
pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
-
pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
-
1.4、aop:after-throwing
-
名称:aop:after-throwing
-
类型:标签
-
归属:aop:aspect标签
-
作用:设置抛出异常后通知
- 格式:
<aop:aspect ref="adviceId">
<aop:after-throwing method="methodName" pointcut="……"/>
</aop:aspect> -
说明:一个aop:aspect标签中可以配置多个aop:after-throwing标签
-
基本属性:
-
method :在通知类中设置当前通知类别对应的方法
-
pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
-
pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
-
1.5、aop:around
-
名称:aop:around
-
类型:标签
-
归属:aop:aspect标签
-
作用:设置环绕通知
- 格式:
<aop:aspect ref="adviceId">
<aop:around method="methodName" pointcut="……"/>
</aop:aspect> -
说明:一个aop:aspect标签中可以配置多个aop:around标签
-
基本属性:
-
method :在通知类中设置当前通知类别对应的方法
-
pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
-
pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
-
环绕通知的开发方式
- 环绕通知是在原始方法的前后添加功能,在环绕通知中,存在对原始方法的显式调用
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object ret = pjp.proceed();
return ret;
}
-
环绕通知方法相关说明:
-
方法须设定Object类型的返回值,否则会拦截原始方法的返回。如果原始方法返回值类型为void,通知方 也可以设定返回值类型为void,最终返回null
-
方法需在第一个参数位置设定ProceedingJoinPoint对象,通过该对象调用proceed()方法,实现对原始方法的调用。如省略该参数,原始方法将无法执行
-
使用proceed()方法调用原始方法时,因无法预知原始方法运行过程中是否会出现异常,强制抛出Throwable对象,封装原始方法中可能出现的异常信息
-
2、通知顺序(了解)
当同一个切入点配置了多个通知时,通知会存在运行的先后顺序,该顺序以通知配置的顺序为准
3、通知获取数据
-
参数
-
返回值
-
异常
3.1、通知获取参数数据
第一种情况:
- 设定通知方法第一个参数为JoinPoint,通过该对象调用getArgs()方法,获取原始方法运行的参数数组
public void before(JoinPoint jp) throws Throwable {
Object[] args = jp.getArgs();
} -
所有的通知均可以获取参数
第二种情况:
-
设定切入点表达式为通知方法传递参数(锁定通知变量名)
-
原始方法
第三种情况
-
设定切入点表达式为通知方法传递参数(改变通知变量名的定义顺序)
-
原始方法
3.2、通知获取返回值数据(around&after-returning)
第一种:返回值变量名
-
设定返回值变量名
- 原始方法
public int save() {
System.out.println("user service running...");
return 100;
} - AOP配置
<aop:aspect ref="myAdvice">
<aop:pointcut id="pt3" expression="execution(* *(..)) "/>
<aop:after-returning method="afterReturning" pointcut-ref="pt3" returning="ret"/>
</aop:aspect> - 通知类
public void afterReturning(Object ret) {
System.out.println(ret);
} -
适用于返回后通知(after-returning)
第二种:
-
在通知类的方法中调用原始方法获取返回值
- 原始方法
public int save() {
System.out.println("user service running...");
return 100;
} - AOP配置
<aop:aspect ref="myAdvice">
<aop:pointcut id="pt2" expression="execution(* *(..)) "/>
<aop:around method="around" pointcut-ref="pt2" />
</aop:aspect> - 通知类
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object ret = pjp.proceed();
return ret;
}
-
适用于环绕通知(around)
3.3、通知获取异常数据
第一种:通知类的方法中调用原始方法捕获异常
-
在通知类的方法中调用原始方法捕获异常
- 原始方法
public void save() {
System.out.println("user service running...");
int i = 1/0;
} - AOP配置
<aop:aspect ref="myAdvice">
<aop:pointcut id="pt4" expression="execution(* *(..)) "/>
<aop:around method="around" pointcut-ref="pt4" />
</aop:aspect> - 通知类
public Object around(ProceedingJoinPoint pjp) throws Throwable {
Object ret = pjp.proceed(); //对此处调用进行try……catch……捕获异常,或抛出异常
return ret;
}
-
适用于环绕通知(around)
第二种:
-
设定异常对象变量名
- 原始方法
public void save() {
System.out.println("user service running...");
int i = 1/0;
} - AOP配置
<aop:aspect ref="myAdvice">
<aop:pointcut id="pt4" expression="execution(* *(..)) "/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pt4" throwing="t"/>
</aop:aspect> - 通知类
public void afterThrowing(Throwable t){
System.out.println(t.getMessage());
}
-
适用于返回后通知(after-throwing)