8.4.5 基于注解的 零配置 方式 8. 定义切入点
正如在前面的FourAdviceTest java
程序中看到的,这个切面类中定义了4个增强处理,定义4个增强处理时分别指定了相同的切入点表达式,这种做法不太符合软件设计原则:因为如果有一天需要修改该切入点表达式,那就要修改4个地方。
定义切入点
为了解决这个问题, AspectJ
和Spring
都允许定义切入点。所谓定义切入点,其实质就是为一个切入点表达式起一个名称,从而允许在多个增强处理中重用该名称。Spring AOP
只支持将Spring Bean
的方法
执行作为连接点,所以可以把切入点看成所有能和切入点表达式匹配的Bean
方法。
切入点定义包含两个部分
- 一个切入点表达式。
- 一个包含名字和任意参数的方法签名。
其中切入点表达式用于指定该切入点和哪些方法进行匹配,包含名字和任意参数的方法签名将作为该切入点的名称。
切入点语法格式
在@AspectJ
风格的AOP
中:
切入点签名
采用一个普通的方法定义(方法体通常为空)来提供,且该方法的返回值必须为void
;切入点表达式
需要使用@Pointcut
注解来标注
下面的代码片段定义了一个切入点:anyOldTransfer
,这个切入点将匹配任何名为transfer
的方法的执行
1 | // 使用`@Pointcut`注解定义切入点 |
切入点表达式,也就是组成@Pointcut
注解的值,是正规的AspectJ
切入点表达式。如果想要更多地了解Aspect
的切入点语言,请参见AspectJ
编程指南。
一旦采用上面的代码片段定义了名为anyOldTransfer
的切入点之后,程序就可多次重复使用该切入点了,甚至可以在其他切面类、其他包的切面类里使用该切入点,至于是否可以在其他切面类、其他包的切面类里访问该切入点,则取决于该方法签名前的访问控制符
—例如,本示例中anyOldTransfer
方法使用private
访问控制符,则意味着仅能在当前切面类中使用该切入点。
引入当前切面类中的切入点
如果需要使用本切面类中的切入点,则可在使用@Before
、@After
、@Around
等注解定义Advice
时,使用pointcut
或value
属性值引用己有的切入点。例如下面的代码片段:
1 | ( |
从上面代码可以看出,指定切入点时非常像调用Java
方法的语法—只是该方法代表一个切入点,其实质是为该增强处理定义一个切入点表达式。
引入其他切面类中的切入点
如果需要使用其他切面类中的切入点,则其他切面类中的切入点不能使用private
修饰。而且在使用@Before
、@After
、@Around
等注解中的pointcut
或vaue
属性值引用已有的切入点时,必须添加类名前缀。
下面程序的切面类里仅定义了一个切入点。
1 | package org.crazyit.app.aspect; |
下面的切面类中将直接使用上面定义的myPointcut()
切入点
1 | package org.crazyit.app.aspect; |
上面程序中的代码就是直接使用SystemArchitecture
类中切入点的代码。当使用其他切面类中的切入点时,应该使用切面类作为前缀来限制切入点。
正如从上面的LogAspect.java
中看到的,该类可以直接使用SystemArchitecture
类中定义的切入点,这意味着其他切面类也可自由使用SystemArchitecture
类中定义的切入点,这就很好地复用了切入点所包含的切入点表达式。