spring里,切面通知总共分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)和环绕通知(Around)五种。我自己写了个例子,了解了下它的原理
1.首先是具体执行的方法:
@Servicepublic class HelloService { public String sayHello(String content){ System.out.println("HelloService: "+content); // if(true) throw new RuntimeException("test"); return "return content: " + content; }}
2.切面代码:
@Aspect@Componentpublic class TestAspect { @Pointcut("execution(* cn.ye.service..*(..))") public void pointcut(){} @Before(value = "pointcut() && args(param)", argNames = "joinPoint,param") public void before(JoinPoint joinPoint, String param){ System.out.println("2 before...."); System.out.println("param:" + param); } @Around("pointcut()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { System.out.println("1 around before...."); Object result = joinPoint.proceed(); System.out.println("3 around after...."); return result; } @After("pointcut()") public void after(JoinPoint joinPoint){ System.out.println("4 after..."); } @AfterReturning(value = "pointcut()", returning = "returnValue") public void afterReturning(JoinPoint joinPoint, Object returnValue){ System.out.println("5 afterReturning..."); System.out.println("return value: " + returnValue); } @AfterThrowing(value = "pointcut()", throwing = "ex") public void afterThrowing(Exception ex){ System.out.println("5 after Throwing..." + ex); }}
3. 如果正常执行,则结果为:
1 around before....2 before....param:YeHelloService: Ye3 around after....4 after...5 afterReturning... //如果抛异常,则本步骤输出 5 after Throwing...java.lang.RuntimeException: test
从上面的结果可以看出,执行的顺序为 around前置逻辑-> before-> 具体逻辑-> around后置逻辑-> after-> afterReturning/afterThrowing
4.接下来可以分析下具体的通知:
- before通知-AspectJMethodBeforeAdvice,从代码可以看出该通知只是执行前置拦截,除非抛出异常,否则不会导致提前返回
- around通知-AspectJAroundAdvice,可以执行前置后置拦截,可以取到返回值
- after通知-AfterReturningAdviceInterceptor->AspectJAfterAdvice,方法执行后在finally中执行,获取不到返回值
- afterReturing通知-AfterReturningAdviceInterceptor->AspectJAfterReturningAdvice,可以取到返回值
- afterThrowing通知-AspectJAfterThrowingAdvice,当出现异常的时候可以取到异常对象,但不影响异常的抛出
5.综上,可以看出:
- before和after通知都是在方法执行前后添加处理逻辑,如果不抛异常是不会影响程序执行逻辑的
- around和afterReturning通知可以取到返回值,其中around通知可以让程序提前返回
- aroundThrowing通知可以获取到程序执行中抛出的异常,但这里捕获异常不会对程序逻辑有影响