一、前置通知
--前置通知
:
在方法执行之前执行的通知
--前置通知使用
@Before
注解
,
并将切入点表达式的值作为注解值。
/**
* 声明该方法是一个前置通知:在目标方法开始之前执行
*/
@Before ( "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" )
public void beforeMethod ( JoinPoint joinPoint ){
System . out . println ( "调用" + joinPoint . getSignature () . getName () + "方法,处理" + Arrays . asList ( joinPoint . getArgs ())) ;
}
* 声明该方法是一个前置通知:在目标方法开始之前执行
*/
@Before ( "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" )
public void beforeMethod ( JoinPoint joinPoint ){
System . out . println ( "调用" + joinPoint . getSignature () . getName () + "方法,处理" + Arrays . asList ( joinPoint . getArgs ())) ;
}
二、后置通知
--
后置通知是在连接点完成之后执行的
,
即连接点返回结果或者抛出异常的时候
,
下面的后置通知记录了方法的终止
/**
* 在目标方法执行后(无论是否发生异常),执行的通知
* 在后置通知中无法访问目标执行的结果
*/
@After ( "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" )
public void afterMethod ( JoinPoint joinPoint ){
System . out . println ( "调用" + joinPoint . getSignature () . getName () + "方法结束" ) ;
}
* 在目标方法执行后(无论是否发生异常),执行的通知
* 在后置通知中无法访问目标执行的结果
*/
@After ( "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" )
public void afterMethod ( JoinPoint joinPoint ){
System . out . println ( "调用" + joinPoint . getSignature () . getName () + "方法结束" ) ;
}
三、返回通知
--在返回通知中, 只要将 returning属性添加到 @AfterReturning注解中, 就可以访问连接点的返回值. 该属性的值即为用来传入返回值的参数名称.
--必须在通知方法的签名中添加一个同名参数. 在运行时, Spring AOP 会通过这个参数传递返回值.
--原始的切点表达式需要出现在 pointcut 属性中
/**
* 在方法正常结束的时候执行
* 返回通知可以获取目标方法的返回值
*/
* 在方法正常结束的时候执行
* 返回通知可以获取目标方法的返回值
*/
@AfterReturning
(value
=
"execution(public int aop.AtithmeticCalculatorImpl.*(int,int))"
, returning
=
"result"
)
public void afterReturningMethod ( JoinPoint joinPoint , Override result ){
System . out . println ( "处理结果为:" + result . toString ()) ;
}
public void afterReturningMethod ( JoinPoint joinPoint , Override result ){
System . out . println ( "处理结果为:" + result . toString ()) ;
}
四、异常通知
--只在连接点抛出异常时才执行异常通知
--将 throwing 属性添加到 @AfterThrowing 注解中, 也可以访问连接点抛出的异常. Throwable是所有错误和异常类的超类. 所以在异常通知方法可以捕获到任何错误和异常.
--如果只对某种特殊的异常类型感兴趣, 可以将参数声明为其他异常的参数类型. 然后通知就只在抛出这个类型及其子类的异常时才被执行.
/**
* 在目标方法出现异常时执行
* 可以访问到方法的异常对象,且可以指定在出现特定异常时在执行通知代码
*/
@AfterThrowing (value = "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" ,throwing = "e" )
public void afterThrowingMethod ( JoinPoint joinPoint , Exception e ){
System . out . println ( joinPoint . getSignature () . getName () + "发生异常:" + e ) ;
}
* 在目标方法出现异常时执行
* 可以访问到方法的异常对象,且可以指定在出现特定异常时在执行通知代码
*/
@AfterThrowing (value = "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" ,throwing = "e" )
public void afterThrowingMethod ( JoinPoint joinPoint , Exception e ){
System . out . println ( joinPoint . getSignature () . getName () + "发生异常:" + e ) ;
}
五、环绕通知
--环绕通知是所有通知类型中功能最为强大的, 能够全面地控制连接点. 甚至可以控制是否执行连接点.
--对于环绕通知来说, 连接点的参数类型必须是 ProceedingJoinPoint. 它是 JoinPoint的子接口, 允许控制何时执行, 是否执行连接点.
--在环绕通知中需要明确调用 ProceedingJoinPoint 的 proceed() 方法来执行被代理的方法. 如果忘记这样做就会导致通知被执行了, 但目标方法没有被执行.
--注意: 环绕通知的方法需要返回目标方法执行之后的结果, 即调用 joinPoint.proceed(); 的返回值, 否则会出现空指针异常
/**
* 环绕方法需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 且环绕通知必须有返回值,返回值为目标方法的返回值
*/
@Around ( "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" )
public Object aroundMethod ( ProceedingJoinPoint pjp ){
Object obj = null ;
try {
//前置通知
System . out . println ( "调用" + pjp . getSignature () . getName () + "方法,处理" + Arrays . asList ( pjp . getArgs ())) ;
//执行方法
obj = pjp . proceed () ;
//返回通知
System . out . println ( "处理结果为:" + obj ) ;
} catch ( Throwable e ) {
//异常通知
System . out . println ( pjp . getSignature () . getName () + "发生异常:" + e ) ;
//抛出异常
throw new RuntimeException ( e ) ;
}
//后置通知
System . out . println ( "调用" + pjp . getSignature () . getName () + "方法结束" ) ;
return obj ;
}
* 环绕方法需要携带ProceedingJoinPoint类型的参数
* 环绕通知类似于动态代理的过程,ProceedingJoinPoint类型的参数可以决定是否执行目标方法
* 且环绕通知必须有返回值,返回值为目标方法的返回值
*/
@Around ( "execution(public int aop.AtithmeticCalculatorImpl.*(int,int))" )
public Object aroundMethod ( ProceedingJoinPoint pjp ){
Object obj = null ;
try {
//前置通知
System . out . println ( "调用" + pjp . getSignature () . getName () + "方法,处理" + Arrays . asList ( pjp . getArgs ())) ;
//执行方法
obj = pjp . proceed () ;
//返回通知
System . out . println ( "处理结果为:" + obj ) ;
} catch ( Throwable e ) {
//异常通知
System . out . println ( pjp . getSignature () . getName () + "发生异常:" + e ) ;
//抛出异常
throw new RuntimeException ( e ) ;
}
//后置通知
System . out . println ( "调用" + pjp . getSignature () . getName () + "方法结束" ) ;
return obj ;
}