在目标方法执行之前执行。被注解为前置通知的方法,可以包含一个 JoinPoint 类型参数。
该类型的对象本身就是切入点表达式。通过该参数,可获取切入点表达式、方法签名、目标对象等。
不光前置通知的方法,可以包含一个 JoinPoint 类型参数,所有的通知方法均可包含该参数。
@Before(value = "execution(* com.ambow.service.impl.SomeServiceImpl.doSome(..))")
public void myBefore(){
System.out.println("前置通知1,在目标方法之前执行。例如:输出日志");
}
@Before(value = "execution(* com.ambow.service.impl.SomeServiceImpl.doSome(..))")
public void myBefore2(JoinPoint jp){
System.out.println("方法定义:" + jp.getSignature());
System.out.println("参数个数:" + jp.getArgs().length);
Object[] args = jp.getArgs();
for (Object arg : args) {
System.out.println(arg);
}
System.out.println("前置通知2,在目标方法之前执行。例如:输出日志");
}
在目标方法执行之后执行。由于是目标方法之后执行,所以可以获取到目标方法的返回值。
该注解的 returning 属性就是用于指定接收方法返回值的变量名的。所以,被注解为后置通知的方法,除了可以包含 JoinPoint 参数外, 还可以包含用于接收返回值的变量。该变量最好为 Object 类型,因为目标方法的返回值可能是任何类型。
接口增加方法:
定义切面:
@AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",returning = "result")
public void myAfterReturnning(Object result){
if (result != null){
String s = (String) result;
result = s.toUpperCase();
}
System.out.println("后置通知,在目标方法之后执行,例如:事务" + result);
}
在目标方法执行之前之后执行。被注解为环绕增强的方法要有返回值, Object 类型。并且方法可以包含一个 ProceedingJoinPoint 类型的参数。
接口 ProceedingJoinPoint 其有一个 proceed()方法,用于执行目标方法。若目标方法有返回值,则该方法的返回值就是目标方法的返回值。最后,环绕增强 方法将其返回值返回。该增强方法实际是拦截了目标方法的执行。
定义切面:
@Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
//环绕通知
System.out.println("环绕通知:在目标方法之前执行");
Object result = pjp.proceed(); //目标方法的调用
//环绕通知
System.out.println("环绕通知,在目标方法之后执行,例如:事务");
return result;
}
在目标方法抛出异常后执行。该注解的 throwing 属性用于指定所发生的异常类对象。当然,被注解为异常通知的方法可以包含一个参数 Throwable,参数名称为 throwing 指定的名称,表示发生的异常对象。
增加业务方法:
@AfterThrowing(value = "execution(* *..SomeServiceImpl.doSecond(..))",throwing = "ex")
public void myAfterThrowing(Throwable ex){
System.out.println("异常通知:在目标方法抛出异常时执行" + ex.getMessage());
}
无论目标方法是否抛出异常,该增强均会被执行。
增加方法:
@After(value = "mypt()")
public void myAfter(){
System.out.println("最终通知:在目标方法之后执行");
}
当较多的通知增强方法使用相同的 execution 切入点表达式时,编写、维护均较为麻烦。AspectJ 提供了@Pointcut 注解,用于定义 execution 切入点表达式。
其用法是,将@Pointcut 注解在一个方法之上,以后所有的 execution 的 value 属性值均可使用该方法名作为切入点。代表的就是@Pointcut 定义的切 入点。这个使用@Pointcut 注解的方法一般使用 private 的标识方法,即没有实际作用的方法。
@Pointcut(value = "execution(* *..SomeServiceImpl.doThird(..))")
public void mypt(){
}