AspectJ (注释方式)

Spring 2.0 以上版本可以使用AspectJ注解或XML配置的AOP。

GitHub Code: feat: AspectJ @before

Spring AOP turorial

引入的包

<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjrt</artifactId>
  <version>1.8.9</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.8.9</version>
</dependency>

5种类型的注解

解释

What is the difference between @Before @After and @AfterExecution in Spring aop

@After: 即使被切的方法执行中发生异常 @After 还是会执行,@After无法获得返回值。

@AfterReturning:可以得到返回值,只有正常返回时才会被执行。

@AfterThrowing:This advice gets executed only when join point method throws exception, we can use it to rollback the transaction declaratively. We use @AfterThrowing annotation for this type of advice.

可以类比java.lang.reflect.InvocationHandler#invoke方法,参看 Proxy.newProxyInstance()创建proxy

执行顺序

GitHub Code: feat: AspectJ @around @after @AfterThrowing @AfterReturning

注意:

  1. 如果同时存在@Around和@AfterThrowing注解的话,上图中有无异常的判断是@Around有没有抛异常,如果@Around修改了被切方法的异常类型,@AfterThrowing接收到的是修改后的异常,如果@Around处理了之后没有在抛出异常,则不会执行@AfterThrowing,而执行的是@AfterReturning。

  2. 如果@Around返回了null,@Around方法本身没有异常,但是如果被切的方法返回值是int,还是会抛出异常,因为类型不匹配。这时执行的还是@AfterReturning,而不会执行@AfterReturning。

  3. 同一个@Aspect注解的类里如果有多个@Before方法,自己测试的结果是 按照方法名字的String排序,小的先执行,beforeMethod6beforeMethod3 后执行,添加@Order或者调换顺序都没有影响。

https://stackoverflow.com/questions/38202051/spring-aop-after-or-afterreturning-which-advice-will-invoked-first

Invocation of the advices of different type applied on the same jointpoint(core business related modules) as follows :

1.Around

2.Before and/or After

3.AfterReturning or AfterThrowing

Suppose we applied all five types of advices on the same jointpoint then the flow will be like :

  1. Around type advice will be invoked and code before pjp.proceed() of Around type advice will be executed where pjp is the reference variable of ProceedingJoinPoint interface.

  2. Before type advice will be invoked and executed fully.

  3. code inside jointpoint will be executed fully.

  4. Code after pjp.proceed() of Around type advice will be executed if jointpoint executes successfully otherwise skip this step and go to step 5. If it's modified return value then this new return value will be effected to the followings advice or method invocation.

  5. After type advice will be invoked and executed fully.

  6. AfterReturning type advice will be invoked and executed fully if jointpoint executes successfully else if jointpoint throws any error then AfterThrowing type advice will be invoked and executed fully.

@Order注解

这个注解针对@Aspect注解的类有效,对里面的方法注解无效,值越小优先级越高,越先被执行。

说实话,存在多个@Aspect注解的切面时挺乱的,如果两个@Aspect注解的类里面只是@Before,执行结果是越小先执行。但是两个@Aspect注解的类里都有@Before @After等多个注解的话,就很乱了,不管有没有@Order,没有像上一节总结的顺序了。

feat: @order 实验,没懂

匹配的表达式

匹配service包下所有类里的方法,service子包里的匹配不了@Before("execution( club.cser.springroad.aop.service..*(..))")

@Pointcut

相同的表达式提出来,其他包里的@Aspect也可以用。

GitHub code: feat: @Pointcut 复用切点表达式

常见的切点表达式

https://segmentfault.com/a/1190000007469968

除了下面这些还有其他的例子

@annotation

匹配由指定注解所标注的方法, 例如:

则匹配由注解 @AuthChecker 所标注的方法.

匹配方法签名

匹配类型签名

匹配 Bean 名字

切点表达式组合

步骤总结

Last updated

Was this helpful?