Spring 框架中切入点 pointcut 表达式的常用写法

本文介绍如何使用AspectJ风格的配置简化Spring AOP的切面管理,提供多个切入点表达式的实例,包括方法执行、参数类型匹配等,帮助开发者更好地理解和应用Spring AOP。

自从使用 AspectJ 风格切面配置,使得 Spring 的切面配置大大简化,但是 AspectJ 是另外一个开源项目,其规则表达式的语法也稍稍有些怪异。

下面给出一些常见示例的写法,例如,下面是一个对 Service 包上所有方法的切面配置:

<aop:config> 
    <aop:pointcut id="serviceOperation" expression="execution(* *..service*..*(..))"/> 
    <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/> 
</aop:config>

表达式所处位置如上pointcut的位置。配置这个是为了更好控制切面上的事务,下面是一个事物配置的简单例子:

<tx:advice id="txAdvice" transaction-manager="transactionManager"> 
      <tx:attributes> 
           <tx:method name="delete*" rollback-for="Exception"/> 
           <tx:method name="save*" rollback-for="Exception"/> 
           <tx:method name="update*" rollback-for="Exception"/> 
           <tx:method name="*" read-only="true" rollback-for="Exception"/> 
       </tx:attributes> 
</tx:advice>

通过切面、通知的配置,就为所有的以deletesaveupdate开头的方法添加上了一致性事务,对其他方法添加上了只读事务。

这个还不够细,如果要写更为详细的控制,就需要研究 AspectJ 切点配置的语法了,其实研究这些标准,还不如拿几个例子看看,解决实际问题就行了。就像写正则表达式一样,标准明摆着,要写好却不容易,从例子着手就能快速上手和领悟。

以下文档来自 Spring 中文开发指南 2.5 文档,由满江红开源组织翻译:

Spring AOP 用户可能会经常使用 execution 切入点指示符。执行表达式的格式如下:

execution(modifiers-pattern? 
ret-type-pattern declaring-type-pattern? 
name-pattern(param-pattern)throws-pattern?

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

任意公共方法的执行:

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 注解的连接点 (在 Spring AOP 中只是方法执行):

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

任何一个只接受一个参数,并且运行时所传入的参数类型具有 @Classified 注解的连接点(在 Spring AOP 中只是方法执行):

@args(com.xyz.security.Classified

任何一个在名为 tradeService 的 Spring bean 之上的连接点 (在 Spring AOP 中只是方法执行):

bean(tradeService)

任何一个在名字匹配通配符表达式*Service的 Spring bean 之上的连接点 (在 Spring AOP 中只是方法执行):

bean(*Service

其中,thistagartargs@target@with@annotation@args在绑定表单中更加常用。


转载声明:本文出自“熔岩”博客,Spring切入点表达式常用写法

<think>我们正在讨论SpringAOP中的切入点表达式语法格式。根据用户提供的引用和之前的上下文,我们知道切入点表达式用于描述哪些方法需要被增强(即应用通知)。引用[3]和[4]明确提到了切入点表达式的标准格式。我们将结合这些引用来回答。切入点表达式标准格式:动作关键字(访问修饰符返回值包名.类/接口名.方法名(参数)异常名)但是,在实际使用中,我们通常不会出所有部分,而是根据需要使用通配符和省略一些可选部分。详细解析:1.动作关键字(最常用的是execution):-表示匹配方法的执行。例如:`execution(...)`2.访问修饰符(可选):-表示方法的访问修饰符,如public,private等。可以省略,省略时表示匹配所有访问权限。3.返回值(必填):-表示方法的返回值类型。使用*可以表示任意返回类型。4.包名.类/接口名.方法名(必填):-指定具体的方法位置。包名可以使用`..`来表示当前包及其子包。类名和方法名可以使用通配符*。5.参数(必填):-方法的参数列表。使用`..`表示任意多个参数(包括0个),也可以使用`*`表示一个任意类型的参数。6.异常名(可选):-方法抛出的异常类型。通常很少使用。示例(来自引用[4]):-精确匹配:`execution(voidcom.itheima.dao.BookDao.update())`-使用通配符:`execution(voidcom.itheima.dao.impl.BookDaoImpl.update())`通用写法技巧(参考引用):-使用通配符`*`:匹配任意字符(除包名分隔符和类名分隔符外)。-例如:`execution(*com.example.service.*.*(..))`表示匹配com.example.service包下任意类的任意方法,参数任意,返回值为任意类型。-使用`..`:在包路径中表示当前包及其子包;在参数列表位置表示任意数量任意类型的参数。-例如:`execution(*com.example..*.*(..))`表示匹配com.example包及其所有子包下的任意类的任意方法。注意事项:-切入点表达式通常以`execution`关键字开始,后面紧跟括号,括号内描述方法签名。-表达式中的各部分之间用空格隔开,但实际上空格并不是强制要求,但为了清晰,建议在关键部分之间加空格。举例:1.匹配所有public方法:```java@Pointcut("execution(public**(..))")```2.匹配指定包下所有方法(不包含子包):```java@Pointcut("execution(*com.example.service.*.*(..))")```3.匹配指定包及其子包下所有类的所有方法:```java@Pointcut("execution(*com.example..*.*(..))")```4.匹配特定类的所有方法:```java@Pointcut("execution(*com.example.service.UserService.*(..))")```5.匹配方法名为特定名称的方法:```java@Pointcut("execution(**..find*(..))")```参考用户提供的引用,我们可以在回答中引用相应的内容。最后,按照用户要求生成相关问题。注意:由于用户要求使用中文,并且使用正确的LaTeX格式(但在这个问题中似乎不太需要数学公式,所以主要注意代码块和引用标识)。</think> ### Spring AOP 切入点表达式语法格式 Spring AOP切入点表达式用于精确描述需要应用通知(Advice)的方法位置。以下是完整的语法规范: #### 📐 标准语法格式 ```java 动作关键字(访问修饰符 返回值 包名.类名.方法名(参数类型) 异常类型) ``` #### 📌 核心组成部分 1. **动作关键字**(必需) 最常用的是 `execution`,表示匹配方法执行 2. **访问修饰符**(可选) 如 `public`、`private` 等,省略时匹配所有访问权限 示例:`public` 或省略 3. **返回值类型**(必需) - 精确类型:`void`, `String`, `int` - 通配符:`*`(匹配任意返回值类型) 示例:`*` 或 `void` 4. **类路径与方法名**(必需) - 包名:可使用 `..` 表示当前包及其子包 - 类名:可使用 `*` 通配符 - 方法名:可使用 `*` 通配符 示例:`com.service..*Service.*(..)` 5. **参数列表**(必需) - `()`:匹配无参方法 - `(类型)`:精确匹配单参数 - `(..)`:匹配任意参数(数量不限) - `(*, String)`:匹配两个参数(第一个任意类型,第二个String) 示例:`(..)` 或 `(String, int)` 6. **异常类型**(可选) 如 `throws IOException`,通常可省略[^3] #### 🔧 通配符使用技巧 | 通配符 | 作用 | 示例 | 效果 | |--------|-----------------------|----------------------|--------------------------| | `*` | 匹配单个单词 | `*.getUser()` | 任意类的getUser方法 | | `..` | 匹配包路径或多参数 | `com..service.*(..)` | com包下所有service类的任意方法 | | `+` | 匹配子类/实现类 | `com.BaseService+` | BaseService及其子类 | #### 🧪 实际用例 1. **匹配指定包下所有方法** ```java @Pointcut("execution(* com.example.service.*.*(..))") ``` 2. **匹配特定类的无参方法** ```java @Pointcut("execution(void com.dao.BookDao.update())") ``` 3. **匹配子包中的方法** ```java @Pointcut("execution(* com..repository.*.find*(..))") ``` 4. **匹配抛出异常的方法** ```java @Pointcut("execution(* *(..) throws IOException)") ``` #### 💡 优化建议 1. 优先使用 `..` 简化包路径描述 2. 用 `*` 替代不关心的元素(如返回值) 3. 参数使用 `(..)` 避免过度限定 4. 将复杂表达式拆分为多个`@Pointcut`组合[^2] > 📌 关键特性:Spring 使用 AspectJ 的切入点语法,但在实现上是基于代理的轻量级方案[^1]。 ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值