Spring发展到现在,基本上能用XML的配置,注解也是可以做到的。回顾下上篇的标签aop:aspect
、aop:pointcut
、aop:before
、aop:after-returning
、aop:after-throwing
、aop:after
、aop:around
如果使用注解的该怎么写?
前置、后置、异常、最终通知
/**
* @Aspect表示是切面,等同于XML中aop:aspect标签
*/
// @EnableAspectJAutoProxy
@Aspect
@Component
public class Logger {
/**
* 切点表达式,对应XML种aop:pointcut标签
*/
@Pointcut("execution(* com.youngledo.service.impl.CustomerServiceImpl.*(..))")
private void pointcut() {}
/**
* pointcut()是上面切点表达式的方法签名,必须这么写
*/
@Before("pointcut()")
public void beforeInfo(JoinPoint joinPoint) {
System.out.println("前置通知:信息开始");
}
@AfterReturning("pointcut()")
public void afterReturningInfo() {
System.out.println("返回通知:信息开始");
}
@AfterThrowing(value = "pointcut()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
System.out.println("异常通知:信息开始");
}
@After("pointcut()")
public void afterFinallyInfo() {
System.out.println("最终通知:信息开始");
}
}
- 执行后正常情况下分别输出:
前置通知:信息开始 最终通知:信息开始 返回通知:信息开始
这个结果是没有问题的,之所以有人说:“为什么最终通知
在返回通知
之前执行呢?”这个还是因为Spring框架把返回通知
放在了最后执行,即finally后面。那再看下异常情况下,又是什么样的执行顺序呢?
- 执行后异常情况下分别输出:
前置通知:信息开始 最终通知:信息开始 异常通知:信息开始
有没有发现异常通知
也是在最终通知
之后执行,按照常理应该是在catch
块种执行才对吧,能解释得通得伙伴留个言。
环绕通知
上面只说了4种类型的通知,就剩最强大的aop:around
通知了。
@Aspect
@Component
public class Logger {
/**
* 切点表达式
*/
@Pointcut("execution(* com.youngledo.service.impl.CustomerServiceImpl.*(..))")
private void pointcut() {}
/**
* @param pjp 该参数是Spring框架为我们封装的代理对象,使用该对象的proceed方法可以调用被代理对象的方法。
* 因此我们可以根据自己实际业务在该方法之前、之后、异常、最终(finally)的时候来增加功能。
*/
@Around("pointcut()")
public Object aroundInfo(ProceedingJoinPoint pjp) {
System.out.println("前置");
try {
// 调用被代理对象的方法,获取返回值
Object result = pjp.proceed();
} catch(Throwable t) {
System.out.println("异常");
} finally {
System.out.println("最终");
}
System.out.println("后置");
return result;
}
}
可以看出环绕通知得灵活性更高,因此我们一般使用该通知来实现。
注意点
再梳理下XML标签与注解得对应关系
XML标签 | 注解 | 解释 |
---|---|---|
aop:config | @EnableAspectJAutoProxy | 开启AOP自动代理 |
aop:aspect | @Aspect | 切面 |
aop:pointcut | @Pointcut | 切点表达式 |
aop:before | @Before | 前置通知 |
aop:after-returning | @AfterReturning | 返回通知 |
aop:after-throwing | @AfterThrowing | 异常通知 |
aop:after | @After | 最终通知 |
aop:around | @Around | 环绕通知 |
需要注意的是@EnableAspectJAutoProxy
是必须的,如果没配置AOP不生效,或者在XML中配置<aop:aspectj-autoproxy />
。并且该注解一般放在统一配置类上。