定义 Aspect
定义一个Aspect,只需要我们定义一个最普通的POJO,然后在类上加上@Aspect
注解即可。
1 | @Aspect |
声明 Pointcut
Pointcut 的声明,依附在@Aspect
所标注的Asepct定义类之内,通过使用@Pointcut
注解,指定Pointcut表达式之后,将这个指定了相应表达式的注解标注到Aspect定义类的某个方法上即可。
1 | @Aspect |
Pointcut 声明包含两部分
- Pointcut Expression,切点表达式。它用来规定Pointcut匹配规则。
- Pointcut Signature,切点签名。它是一个具体化的方法定义,是Pointcut Expression的载体。
1 | @Aspect |
上面我们就简单定义了一个pointcut,它将匹配到所有方法名为method1且返回值为void的方法。
Pointcut标志符(Pointcut Designator)
上面例子execution(void *.method1())
中的execution
即为Pointcut标志符。它表明该Pointcut将以什么样的行为来匹配表达式。
- execution - 匹配指定方法。
- within - 匹配指定类下所声明的所有方法。如
withIn(com.liuqitech.spring.aop.MoctTarget)
它将匹配MockTarget
类中所有声明的方法。 - this - limits matching to join points (the execution of methods when using Spring AOP) where the bean reference (Spring AOP proxy) is an instance of the given type
- target - limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type
- args - 匹配参数满足要求的方法。如
args(com.liuqitech.spring.aop.domain.User)
它将匹配所有仅有一个入参且类型为com.liuqitech.spring.aop.domain.User
的方法(比如:public boolean login(User user){...}
、public boolean isLogin(User){...}
) @target
- limits matching to join points (the execution of methods when using Spring AOP) where the target object (application object being proxied) is an instance of the given type@args
- 匹配入参被某注解标注的方法。@within
- 匹配使用了某注解的类下所有的方法。比如@withIn(org.springframework.stereotype.Component)
它将匹配所有使用了@Component
注解的类下所有声明的方法。- @annotation - 匹配使用了某注解的方法。
声明Advice
它实际上就是使用@Aspect
标注的Aspect定义类中的不同方法,只不过这些方法需要针对不同的Advice类型使用对应的注解进行标注。
- @Before,前置增强
- @AfterReturning,后置增强,
- @AfterThrowing,抛出增强
- @After,Final增强
- @Around,环绕增强
- @DeclareParents,引介增强
除了@DeclareParents
比较不同之外,其他用于标注不同类型Advice的注解,全都是方法级别的注解定义,只能用于标注方法定义。同时,各种Advice最终织入到什么位置,是由相应的Pointcut定义决定的。所以我们需要为这些用于标注Advice的注解指定对应的Pointcut定义,可以直接使用的Pointcut表达式,也可以指定上面单独声明的@Pointcut类型的Pointcut Signature。
1 | @Aspect |
@AfterThrowing 示例
1 | @Aspect |
它有一个独特的属性throwing
,通过它我们可以限定Advice定义方法的参数名,并在方法调用的时候,将相应的异常绑定到具体方法参数上。当然如果不需要访问具体异常,那么我们可以声明没有任何参数的方法。
1 | @AfterThrowing(pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation()") |
@AfterReturning 示例
1 | @Aspect |
它也有一个独特的属性returning
,它能获取方法的返回值。当然如果我们不需要方法返回值时,也可以去掉该属性。
@Around 示例
1 | @Aspect |
该类型的方法定义中,第一个参数必须是ProceedingJoinPoint
类型,我们需要通过ProceedingJoinPoint的proceed()方法继续执行调用链。