Spring 事物 expression="execution(*service..*.*(..))"

本文详细介绍了 Spring AOP 中的切入点表达式配置方法,包括通配符的意义及使用方式,如何配置事务管理等,为开发者提供了实用的指导。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(* com.evan.crm.service.*.*(..))中几个通配符的含义: 


|第一个 * —— 通配 随便率性返回值类型| 
|第二个 * —— 通配包com.evan.crm.service下的随便率性class| 
|第三个 * —— 通配包com.evan.crm.service下的随便率性class的随便率性办法| 
|第四个 .. —— 通配 办法可以有0个或多个参数| 


 

 

<!-- 配置那些类的方法进行事务管理 --> 
<aop:config> 
<aop:pointcut id="allServiceMethod" expression="execution (* com.cms.sys.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethod" /> 
</aop:config> 

还有一个 
execution (* com.cms.art.service.*.*(..))" 

要怎么写?

可以这样写:将execution分开写。 
<aop:config> 
<aop:pointcut id="allServiceMethod" expression="(execution (* com.cms.sys.service.*.*(..)))or (execution (* com.cms.art.service.*.*(..)))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethod" /> 
</aop:config> 


例如:

<!-- Hibernate 事务控制配置 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
<property name="nestedTransactionAllowed" value="true" />
</bean>
<!-- 使用Hibernate的事务控制器管理事务 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="save*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="update*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="del*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="remove*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="add*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="insert*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="auth*" rollback-for="Exception" propagation="REQUIRED" />
<tx:method name="*" rollback-for="Exception" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<!-- 使用对实体类的事务控制 -->
<aop:config proxy-target-class="true">
<aop:advisor pointcut="execution(* com.rf..*.*Service.*(..))" advice-ref="txAdvice" />
<aop:advisor pointcut="execution(* com..*.*Service.*(..))" advice-ref="txAdvice" />

</aop:config>


==========================================================================================================

execution切入点表达式


Spring AOP 用户可能会经常使用 execution切入点指示符。执行表达式的格式如下:
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern? name-pattern(param-pattern)
          throws-pattern?)
除了返回类型模式(上面代码片断中的ret-type-pattern),名字模式和参数模式以外, 所有的部分都是可选的。返回类型模式决定了方法的返回类型必须依次匹配一个连接点。 
使用的最频繁的返回类型模式是*,它代表了匹配任意的返回类型。 一个全限定的类型名将只会匹配返回给定类型的方法。名字模式匹配的是方法名。 
使用*通配符作为所有或者部分命名模式。 
类型匹配模式:
1:*:匹配任何数量字符;比如模式 (*,String) 匹配了一个接受两个参数的方法,第一个可以是任意类型,第二个则必须是String类型
2:..:匹配任何数量字符的重复,如在类型模式中匹配任何数量子包;而在方法参数模式中匹配任何数量参数,可以使零到多个。
3: +:匹配指定类型的子类型;仅能作为后缀放在类型模式后边。
参数匹配模式:
()匹配了一个不接受任何参数的方法,
(..)匹配了一个接受任意数量参数的方法(零或者更多)。 
(*)匹配了一个接受一个任何类型的参数的方法。 
(*,String)匹配了一个接受两个参数的方法,第一个可以是任意类型, 第二个则必须是String类型。

下面给出一些通用切入点表达式的例子。
  • 任意公共方法的执行:
    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)
    'this'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得代理对象在通知体内可用。
  • 实现AccountService接口的目标对象的任意连接点 (在Spring AOP中只是方法执行):
    target(com.xyz.service.AccountService)
    'target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得目标对象在通知体内可用。
  • 任何一个只接受一个参数,并且运行时所传入的参数是Serializable 接口的连接点(在Spring AOP中只是方法执行)
    args(java.io.Serializable)
    'args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得方法参数在通知体内可用。
    请注意在例子中给出的切入点不同于 execution(* *(java.io.Serializable)): args版本只有在动态运行时候传入参数是Serializable时才匹配,而execution版本在方法签名中声明只有一个 Serializable类型的参数时候匹配。
  • 目标对象中有一个 @Transactional 注解的任意连接点 (在Spring AOP中只是方法执行)
    @target(org.springframework.transaction.annotation.Transactional)
    '@target'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个目标对象声明的类型有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行):
    @within(org.springframework.transaction.annotation.Transactional)
    '@within'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个执行的方法有一个 @Transactional 注解的连接点 (在Spring AOP中只是方法执行)
    @annotation(org.springframework.transaction.annotation.Transactional)
    '@annotation'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个只接受一个参数,并且运行时所传入的参数类型具有@Classified 注解的连接点(在Spring AOP中只是方法执行)
    @args(com.xyz.security.Classified)
    '@args'在绑定表单中更加常用:- 请参见后面的通知一节中了解如何使得注解对象在通知体内可用。
  • 任何一个在名为'tradeService'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
    bean(tradeService)
  • 任何一个在名字匹配通配符表达式'*Service'的Spring bean之上的连接点 (在Spring AOP中只是方法执行):
    bean(*Service)

Spring AOP中,AspectJ切点表达式用于定义哪些方法需要被拦截并应用切面逻辑。这两个表达式 `execution(* com.po..*.*service.impl.*.*(..))` 和 `execution(* com.po..*service.impl.*.*(..))` 都试图匹配 `com.po` 包及其子包下的某些类和方法,但它们之间存在细微差别。 ### 表达式分析 #### 1. `execution(* com.po..*.*service.impl.*.*(..))` 这个表达式的含义是: - `execution(...)`:表示匹配任何方法执行。 - `*`:返回类型可以是任意类型。 - `com.po`:指定根包为 `com.po`。 - `..*`:表示匹配 `com.po` 包下的所有子包(包括多层嵌套的子包)。 - `.*service.impl.`:表示在这些子包中查找名称以 `.service.impl.` 结尾的包中的类。 - `*`:表示匹配该包中的所有类。 - `*`:表示匹配该类中的所有方法。 - `(..)`:表示方法参数可以是任意数量和类型的参数。 因此,这个表达式会匹配 `com.po` 包及其所有子包中,位于 `.service.impl.` 包下的所有类的所有方法。例如,它可以匹配 `com.po.user.service.impl.UserService` 类中的所有方法 [^2]。 #### 2. `execution(* com.po..*service.impl.*.*(..))` 这个表达式的含义是: - `execution(...)`:表示匹配任何方法执行。 - `*`:返回类型可以是任意类型。 - `com.po`:指定根包为 `com.po`。 - `..*service.impl.`:表示匹配 `com.po` 包下所有子包中名称以 `*service.impl.` 结尾的包中的类。这里的 `*` 是一个通配符,表示前面的部分可以有任意字符,只要最终形成 `*service.impl.` 的结构即可。 - `*`:表示匹配该包中的所有类。 - `*`:表示匹配该类中的所有方法。 - `(..)`:表示方法参数可以是任意数量和类型的参数。 因此,这个表达式会匹配 `com.po` 包及其所有子包中,名称以 `*service.impl.` 结尾的包中的所有类的所有方法。例如,它可以匹配 `com.po.order.service.impl.OrderService` 类中的所有方法 [^2]。 ### 区别总结 - **第一种表达式** `execution(* com.po..*.*service.impl.*.*(..))` 更加具体,它要求包名必须以 `.service.impl.` 结尾,并且该包必须存在于 `com.po` 包及其子包中。这种写法更倾向于匹配那些明确命名为 `.service.impl.` 的包中的类和方法。 - **第二种表达式** `execution(* com.po..*service.impl.*.*(..))` 更加灵活,它允许包名以任意字符开头,只要最终形成 `*service.impl.` 的结构即可。这意味着它可以匹配更多种类的包名,如 `orderservice.impl`、`userservice.impl` 等等 [^2]。 ### 示例代码 假设有一个项目结构如下: ``` com └── po ├── user │ └── service │ └── impl │ └── UserService.java └── order └── service └── impl └── OrderService.java ``` 对于上述结构,第一个表达式将匹配 `UserService` 和 `OrderService` 类中的所有方法,而第二个表达式同样也会匹配这两个类中的所有方法。但如果存在另一个类 `com.po.payment.service.impl.PaymentService`,那么两个表达式都会匹配到它 [^2]。 ### 相关问题 1. 如何在Spring AOP中定义多个切点? 2. Spring AOP与AspectJ的区别是什么? 3. 如何在Spring AOP中使用注解来定义切点? 4. 如何在Spring Boot中配置AOP? 5. 如何调试Spring AOP中的切点匹配问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值