使用After增强处理
Spring还提供了一个After增强处理,它与AfterReturning有点类似,但也有区别:
AfterReturning增强处理只有在目标方法正确完成后才会被织入
After增强处理不管目标方法如何结束(正确还是异常),它都会被织入
正是因为这个特点,因此After增强处理必须准备处理正常返回和异常返回两种情况,这种增强处理通常用于释放资源。使用@After注解标注一个方法,即可将该方法转换为After增强处理。使用@After注解是需要指定一个value属性,用于指定该增强处理的切入点,既可以是一个已有的切入点,也可以直接定义切入点表达式。
在com.abc.advice包下面增加AfterAdviceTest,这个类定义了一个After增强处理:
@Aspect
public class AfterAdviceTest {
@After(value="execution(* com.abc.servie.impl.*.afterAdvice*(..))")
public void releaseResource() {
System.out.println("模拟释放数据库连接");
}
}
并在AdviceManager类中增加以下内容:
//将被AfterAdvice的releaseResource方法匹配
public void afterAdvice() {
System.out.println("方法: afterAdvice");
}
上面定义了一个After增强处理,不管切入点的目标方法如何结束,该增强处理都会被织入。下面是测试结果:
使用Around增强处理
@Around注解用于标注Around增强处理,它近似等于Before增强处理和AfterReturning增强处理的总和,Around增强处理既可以在执行目标方法前织入增强动作,也可以在目标方法之后织入增强动作。
与@Before和@AfterReturning不同的是,@Around甚至可以决定目标方法在什么时候执行,如何执行,甚至可以完全阻止目标方法的执行。@Around可以修改目标方法的参数值,也可以修改目标方法的返回值。
@Around的功能虽然强大,但通常需要在线程安全的环境下使用,因此,如果使用普通的@Before和@AfterReturning就能解决的问题,就没有必要使用@Around了。如果需要目标方法执行之前和执行之后共享某种数据状态,则应该考虑使用@Around;尤其是需要使用增强处理阻止目标方法的执行,或者需要改变目标方法的参数和执行后的返回值时,就只能使用@Around了。
可以想象,使用@Around时,也需要指定一个value属性,这个属性依然是用于指定切入点。另外,当定义一个Around增强处理时,该方法的第一个形参必须是ProceedingJoinPoint类型(就是说至少包含一个形参),在增强处理方法体内,调用ProceedingJoinPoint的proceed()方法才会执行目标方法——这就是Around增强处理可以完全控制目标方法的执行时机、如何执行的关键,如果增强处理的方法体内没有调用这个proceed()方法,则目标方法不会执行。
调用proceed()方法时,还可以传入一个Object[]对象,该数组中的值将被传入目标方法作为执行方法的实参。因此我们可以通过这个参数,修改方法的参数值。
在com.abc.advice包下面增加AroundAdviceTest,这个类定义了一个Around增强处理:
package com.abc.advice;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class AroundAdviceTest {
@Around(value="execution(* com.abc.service.*.around*(..))")
public Object process(ProceedingJoinPoint point) throws Throwable {
System.out.println("模拟执行目标方法前的增强处理:事务开始...");
//修改目标方法的参数
String[] params = new String[]{"param1"};
//执行目标方法,并保存目标方法执行后的返回值
Object returnValue = point.proceed(params);
System.out.println("模拟执行目标方法后的增强处理:事务结束...");
//返回修改后的返回值
return "方法实际返回值:" + returnValue + ",这是返回值的后缀";
}
}
上面定义了一个AroundAdviceTest切面,该切面包含了一个Around增强处理:process()方法,该方法中第一行代码用于模拟调用目标方法之前的处理,第二行修改了目标方法的第一个参数,接下来调用目标方法,后面模拟调用目标方法之后的处理和对返回值的修改。正如前面说的,通过这个process方法,我们可以增加类似于@Before和@AfterReturning的增强处理,可以决定什么时候执行目标方法,可以修改目标方法的参数值,还可以修改目标方法的返回值,真是想做什么就做什么啊!
在AdviceManager类中增加以下内容:
//将被AroundAdvice的process方法匹配
public String aroundAdvice(String param1) {
System.out.println("方法: aroundAdvice");
return param1;
}
在com.abc.main.AOPTest中加入方法的调用,触发切点:
String result = manager.aroundAdvice("param1");
System.out.println("返回值:" + result);
执行测试类,结果如下:
需要注意的是,当调用ProceedingJoinPoint的proceed()方法时,传入的Object[]参数值将作为目标方法的参数,如果这个数组长度与目标方法的参数个数不等,或者数组元素的类型和目标方法的参数类型不匹配,程序就会出现异常。
《Spring中的AOP系列三、四、五》的代码在这里:点击下载,欢迎留言提意见。
【未完,待续】