前置通知
使用@Before
第一种方法:先定义pointcut
@Pointcut("execution(* com..*.sleep(..))")
public void callSleep(){}
@Before(value="callSleep()")
public void beforeSleep(JoinPoint joinPoint){
System.out.println("before sleep");
}
第二种方法将pointcut写在@Before
中
@Before("within(com.codestd.springstudy.aop.People)")
public void beforeSleep(JoinPoint joinPoint){
System.out.println("before sleep");
}
@Before("execution(* com..*.sleep(..))")
public void beforeSleep(JoinPoint joinPoint){
System.out.println("before sleep");
}
后置通知
@After(value = "callSleep()")
public void afterSleep(){
System.out.println("after sleep");
}
---
@After("execution(* com..*.sleep(..))")
public void beforeSleep(JoinPoint joinPoint){
System.out.println("before sleep");
}
获取目标对象
在前置通知和后置通知中可以将JoinPoint
作为方法的参数传入通知方法(如上)。
joinPoint.getTarget() //获取目标对象
joinPoint.getArgs() //获取连接点方法运行时的入参列表
joinPoint.getSignature() //获取连接点的方法签名对象
joinPoint.getThis() //获取代理对象本身
环绕通知
通知优先级如下环绕通知-->前置通知-->后置通知-->环绕通知
//@Around("execution(* com..*.sleep(..))")
@Around(value = "callSleep()")
public Object afterSleep(ProceedingJoinPoint joinPoint) throws Throwable{
// start stopwatch
Object retVal = joinPoint.proceed();
// stop stopwatch
return retVal;
}
在环绕通知中使用ProceedingJoinPoint
获取连接点信息,需要在环绕通知调用连接点的proceed()
方法手动执行方法,并且将方法的返回值作为通知方法的返回值返回。
ProceedingJoinPoint继承JoinPoint子接口,它新增了两个用于执行连接点方法的方法:
- java.lang.Object proceed() throws java.lang.Throwable:通过反射执行目标对象的连接点处的方法;
- java.lang.Object proceed(java.lang.Object[] args) throws java.lang.Throwable:通过反射执行目标对象连接点处的方法,不过使用新的入参替换原来的入参。