Spring 学习4--AOP Execution

来源:互联网 发布:网络节点分为三类 编辑:程序博客网 时间:2024/06/06 04:33

        除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外,所有的部分都是可选的。 返回类型模式决定了方法的返回类型必须依次匹配一个连接点。你会使用的最频繁的返回类型模式是 *,它代表了匹配任意的返回类型。一个全称限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。你可以使用 * 通配符作为所有或者部分命名模式。参数模式稍微有点复杂:() 匹配了一个不接受任何参数的方法,而 (..)匹配了一个接受任意数量参数的方法(零或者更多)。模式 (*) 匹配了一个接受一个任何类型的参数的方法。模式 (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型。 请参见AspectJ编程指南的 Language Semantics 部分。

1.下面给出一些常见切入点表达式的例子。

  • 任意公共方法的执行:

execution(public* *(..))

  • 任何一个以“set”开始的方法的执行:

execution(*set*(..))

  • AccountService 接口的任意方法的执行:

execution(*com.xyz.service.AccountService.*(..))

  • 定义在service包里的任意方法的执行:

execution(*com.xyz.service.*.*(..))

  • 定义在service包或者子包里的任意方法的执行:

execution(*com.xyz.service..*.*(..))

  • 在service包里的任意连接点(在Spring AOP中只是方法执行) :

within(com.xyz.service.*)

  • 在service包或者子包里的任意连接点(在Spring AOP中只是方法执行) :

within(com.xyz.service..*)

  • 实现了 AccountService 接口的代理对象的任意连接点(在Spring AOP中只是方法执行) :

this(com.xyz.service.AccountService)

  • 实现了 AccountService 接口的目标对象的任意连接点(在Spring AOP中只是方法执行) :

target(com.xyz.service.AccountService)

  • 任何一个只接受一个参数,且在运行时传入的参数实现了 Serializable 接口的连接点 (在Spring AOP中只是方法执行)

args(java.io.Serializable)

请注意在例子中给出的切入点不同于 execution(* *(Java.io.Serializable)) args只有在动态运行时候传入参数是可序列化的(Serializable)才匹配,而execution 在传入参数的签名声明的类型实现了Serializable 接口时候匹配。

  • 有一个 @Transactional 注解的目标对象中的任意连接点(在Spring AOP中只是方法执行)

@target(org.springframework.transaction.annotation.Transactional)

  • 任何一个目标对象声明的类型有一个 @Transactional 注解的连接点(在Spring AOP中只是方法执行)

@within(org.springframework.transaction.annotation.Transactional)

  • 任何一个执行的方法有一个 @Transactional annotation的连接点(在Spring AOP中只是方法执行)

@annotation(org.springframework.transaction.annotation.Transactional)

  • 任何一个接受一个参数,并且传入的参数在运行时的类型实现了 @Classified annotation的连接点(在Spring AOP中只是方法执行)

@args(com.xyz.security.Classified)

 

2.解释及举例

execution(*com.sample.service.impl..*.*(..))

解释如下:

符号

含义

execution()

表达式的主体;

第一个”*“符号

表示返回值的类型任意;

com.sample.service.impl

AOP所切的服务的包名,即,我们的业务部分

包名后面的”..“

表示当前包及子包

第二个”*“

表示类名,*即所有类。此处可以自定义,下文有举例

.*(..)

表示任何方法名,括号表示参数,两个点表示任何参数类型



AspectJ中的exection表达式小结:

基本语法格式为:

execution(<修饰符模式>?<返回类型模式><方法名模式>(<参数模式>)<异常模式>?)  除了返回类型模式、方法名模式和参数模式外,其它项都是可选的。

下面,我们给出各种使用execution()函数实例。

1)通过方法签名定义切点

 execution(public* *(..))

匹配所有目标类的public方法,但不匹配SmartSeller和protected voidshowGoods()方法。第一个*代表返回类型,第二个*代表方法名,而..代表任意入参的方法;

 execution(**To(..))l

匹配目标类所有以To为后缀的方法。它匹配NaiveWaiter和NaughtyWaiter的greetTo()和serveTo()方法。第一个*代表返回类型,而*To代表任意以To为后缀的方法;

2)通过类定义切点

 execution(*com.baobaotao.Waiter.*(..))l

匹配Waiter接口的所有方法,它匹配NaiveWaiter和NaughtyWaiter类的greetTo()和serveTo()方法。第一个*代表返回任意类型,com.baobaotao.Waiter.*代表Waiter接口中的所有方法;

 execution(*com.baobaotao.Waiter+.*(..))l

匹配Waiter接口及其所有实现类的方法,它不但匹配NaiveWaiter和NaughtyWaiter类的greetTo()和serveTo()这两个Waiter接口定义的方法,同时还匹配NaiveWaiter#smile()和NaughtyWaiter#joke()这两个不在Waiter接口中定义的方法。 

3)通过类包定义切点

在类名模式串中,“.*”表示包下的所有类,而“..*”表示包、子孙包下的所有类。

 execution(*com.baobaotao.*(..))l

匹配com.baobaotao包下所有类的所有方法; 

 execution(*com.baobaotao..*(..))l

匹配com.baobaotao包、子孙包下所有类的所有方法,如com.baobaotao.dao,com.baobaotao.servier以及com.baobaotao.dao.user包下的所有类的所有方法都匹配。“..”出现在类名中时,后面必须跟“*”,表示包、子孙包下的所有类;

 execution(*com..*.*Dao.find*(..))l

匹配包名前缀为com的任何包下类名后缀为Dao的方法,方法名必须以find为前缀。如com.baobaotao.UserDao#findByUserId()、com.baobaotao.dao.ForumDao#findById()的方法都匹配切点。

4)通过方法入参定义切点

切点表达式中方法入参部分比较复杂,可以使用“*”和“..”通配符,其中“*”表示任意类型的参数,而“..”表示任意类型参数且参数个数不限。

 execution(*joke(String,int)))l

匹 配joke(String,int)方法,且joke()方法的第一个入参是String,第二个入参是int。它匹配NaughtyWaiter#joke(String,int)方法。如果方法中的入参类型是Java.lang包下的类,可以直接使用类名,否则必须使用全限定类名,如joke(java.util.List,int);

 execution(*joke(String,*)))l

匹 配目标类中的joke()方法,该方法第一个入参为String,第二个入参可以是任意类型,如joke(Strings1,Strings2)和joke(String s1,double d2)都匹配,但joke(String s1,doubled2,String s3)则不匹配;

 execution(*joke(String,..)))l

匹配目标类中的joke()方法,该方法第 一个入参为String,后面可以有任意个入参且入参类型不限,如joke(Strings1)、joke(String s1,String s2)和joke(Strings1,double d2,Strings3)都匹配。

 execution(*joke(Object+)))

匹 配目标类中的joke()方法,方法拥有一个入参,且入参是Object类型或该类的子类。它匹配joke(Strings1)和joke(Client c)。如果我们定义的切点是execution(*joke(Object)),则只匹配joke(Object object)而不匹配joke(Stringcc)或joke(Client c)。

3.例子

/**

 * 定义一个切入点.

 * 解释下:

 *

 * ~ 第一个 * 代表任意修饰符及任意返回值.

 * ~ 第二个 * 任意包名

 * ~ 第三个 * 代表任意方法.

 * ~ 第四个 * 定义在web包或者子包

 * ~ 第五个 * 任意方法

 * ~ .. 匹配任意数量的参数.

**/

 @Pointcut("execution(public * com.kfit.*.web..*.*(..))")

 publicvoid webLog(){}

 


0 0
原创粉丝点击