切点表达式的作用
无论是使用XML还是注解的方式配置AOP,其中有一步比较重要的关键点是:如何准确的对需要增强的方法进行增强。这个定位问题的解决方案就是:切点表达式。
以XML的方式 学习切点表达式
切点表达式,是用来锁定目标方法的。
我们以XML为详细介绍,注解因为相对来说较为简单所以,你了解配置文件的话一定就能动过注解方式。
回顾:XML
切面
需要写在<aop:config> </aop:config>
中切面
在XML中以<aop:aspect> </aop:aspect>
定义
<aop:config>
<aop:aspect id="切面在Spring容器中的id" ref="切面对应在Spring容器中实际的类">
</aop:aspect>
</aop:config>
- 正如上面代码中文标注的
ref="切面对应在Spring容器中实际的类"
,这里的切面是实际对应容器中的一个Bean,这个Bean是一个加强类,所谓加强类就是将用来增强的方法定义在了这个Bean中。那么ref
应该是指向XML文件中已经定义好的Bean
<bean id="xmlAop" class="spring_06_40_43_basic.basic_42.logger.XmlAop"></bean>
<aop:config>
<aop:aspect id="切面在Spring容器中的id" ref="xmlAop">
</aop:aspect>
</aop:config>
切面
实际上是一个类,类中是有方法(增强方法)的,这些增强方法可以在目标方法执行前、后...在Spring中分别有:
- before 前置通知:目标对象的方法调用之前触发。
- after后置通知:目标对象的方法调用之后触发。
- afterReturning 返回通知:目标对象的方法调用完成,在返回结果值之后触发。
- afterThrowing 异常通知:目标对象的方法运行中抛出 / 触发异常后触发。
- around 环绕通知:编程式控制目标对象的方法调用。
分别对应的在XML中:
<aop:before></aop:before>
<aop:after></aop:after>
<aop:afterReturning></aop:afterReturning>
<aop:afterThrowing></aop:afterThrowing>
<aop:around></aop:around>
以前置通知<aop:before></aop:before>
为例
<aop:config>
<aop:aspect id="切面在Spring容器中的id" ref="xmlAop">
<aop:after></aop:after>
</aop:aspect>
</aop:config>
我们主要配置的属性有:method
和pointcut
<aop:after method="XXX"
pointcut="XXX"></aop:after>
- method:对应切面类中的方法,也就是
spring_06_40_43_basic.basic_42.logger.XmlAop
这个类中的方法。 - pointcut:具体给目标类的哪个方法做增强,终于到正题了。
切点表达式
切点表达式都以
execution("")
包围
切点表达式主要是:描述目标方法的。因为method
方法已经表示的是增强方法,那么增强给谁呢?这个工作交给了pointcut
想象一下 我们怎么描述方法的,按照我们的想象,我给出了下面的文字帮助记忆:
公开的/私有的,返回值是什么,方法是属于哪个类的,方法名是什么,参数个数或类型
例子:public void com.chengyunlai.service.UserService.login (String,Integer)
这个例子说的是方法必须是:
- 公开的
- 返回值是void,也就是不返回
- 在UserService中(全类名表示)
- 方法名是login
- 参数类型必须是
String
和Integer
切点表达式覆盖多个类或者多个方法
那就记住这两个特殊符号:
*
:表示任意..
:表示任意个- 返回值类型、包名、类名、方法名可以使用
*
号代替表示任意 .
表示当前包..
代表当前包及其子包下的类- 参数列表可以使用
..
表示任意个数的任意参数列表
例子都以public
和void
- 例子:
com.chengyunlai.service
包下的任意类,任意方法,任意参数
public void com.chengyunlai.service.*.* (..)
- 例子:
com.chengyunlai.service.UserService
这个UserService
类的任意参数的任意方法(就全部方法啦)
public void com.chengyunlai.service.UserService.* (..)
- 例子:
com.chengyunlai
该包及其自包下任意类的所有参数为String
的方法
public void com.chengyunlai..*.* (String)
所以,再加上execution()
,完整的切点表达式:
execution("public void com.chengyunlai.service.*.* (..)")
附录注解对应XML
- 配置类需要加上
@EnableAspectJAutoProxy
,可以理解对应<aop:config>
- 切面类需要加上
@Aspect
,对应<aop:aspect>
- 切面类的方法需要加上
@After
,对应<aop:after>
(就不一一例举了) - 在
@After()
中添加切点表达式,与XML的方式一样。