@Transactional注意事项

本文详细解析了Spring框架中@Transactional注解的使用方式与注意事项,包括如何正确应用注解以确保事务的有效性,以及不同代理类型(如基于接口和基于类的代理)对事务管理的影响。
[*][b]@Transactional[/b]注解可以被应用于接口定义和接口方法、类定义和类的[b] public[/b] 方法上。
[*][b]proxy-target-class[/b] 属性值来控制是基于接口的还是基于类的代理被创建。
<tx:annotation-driven transaction-manager=“transactionManager” proxy-target-class=“true”/> 
注意:proxy-target-class属性值决定是基于接口的还是基于类的代理被创建。如果proxy-target-class 属性值被设置为true,那么基于类的代理将起作用(这时需要cglib库)。如果proxy-target-class属值被设置为false或者这个属性被省略,那么标准的JDK 基于接口的代理。
[*][b]@Transactional[/b] cglib与java动态代理最大区别是代理目标对象不用实现接口,那么注解要是写到接口方法上,要是使用cglib代理,这是注解事务就失效了,为了保持兼容注解最好都写到实现类方法上。
[*]Spring团队建议在[b]具体的类[/b](或类的方法)上使用 [b]@Transactional[/b] 注解,而不要使用在类所要实现的任何接口上。
在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。因为注解是 不能继承的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象被事务代理所包装。

[*][b]@Transactional[/b] 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。 原因: spring 在扫描bean的时候会扫描方法上是否包含@Transactional注解,如果包含,spring会为这个bean动态地生成一个子类(即代理类,proxy),代理类是继承原来那个bean的。此时,当这个有注解的方法被调用的时候,实际上是由代理类来调用的,代理类在调用之前就会启动transaction。然而,如果这个有注解的方法是被同一个类中的其他方法调用的,那么该方法的调用并没有通过代理类,而是直接通过原来的那个bean,所以就不会启动transaction,我们看到的现象就是@Transactional注解无效。
### 关于 `@Transactional` 注解的使用说明与注意事项 #### 1. **适用范围** `@Transactional` 注解主要用于管理 Spring 应用程序中的事务行为。该注解可以应用于类级别或方法级别,用于定义事务边界以及控制事务的行为。 - 当注解作用于类时,表示该类下的所有公共方法都将默认具有相同的事务特性[^2]。 - 若某个具体方法也标注了 `@Transactional`,则此方法的事务配置会覆盖类级别的事务设置。 #### 2. **可见度限制** `@Transactional` 注解仅能应用到 `public` 方法上。如果将其放置在 `protected`、`private` 或包级访问权限的方法上,则事务机制不会生效,尽管编译器不会抛出错误[^3]。 #### 3. **代理模式的影响** Spring 默认通过动态代理实现事务管理功能。这意味着只有外部调用受 `@Transactional` 控制的方法才会触发事务逻辑;而同一对象内部方法之间的相互调用无法激活事务支持[^1]。 #### 4. **异常处理机制** 默认情况下,只有遇到运行时异常 (`RuntimeException`) 或错误 (`Error`) 才会使事务回滚。对于其他类型的检查型异常 (Checked Exception),除非显式声明,否则不会引发回滚操作。可以通过设置属性 `rollbackFor` 来指定额外需要触发回滚的异常类型,或者利用 `noRollbackFor` 排除某些特定情况不进行回滚。 以下是示例代码片段: ```java import org.springframework.transaction.annotation.Transactional; @Service public class MyService { @Transactional(rollbackFor = {IllegalArgumentException.class}) public void processTransaction() { // 数据库操作... throw new IllegalArgumentException("Test rollback"); } } ``` 在此例子中,即使抛出了 `IllegalArgumentException` 这样的非运行时异常,由于我们设置了 `rollbackFor` 属性,因此仍然能够促使事务回滚。 #### 5. **传播行为** `@Transactional` 提供多种传播行为选项来决定当前事务如何与其他已有事务交互。常见的有 REQUIRED(存在即加入现有事务,不存在则创建新事务)、REQUIRES_NEW(总是启动新的独立事务)等。开发者应依据实际需求合理选择合适的传播策略以保障数据一致性。 ### 总结 综上所述,在日常开发过程中正确运用 `@Transactional` 需要注意其适用场景、方法可见性约束、代理机制局限性以及精确设定异常响应规则等方面的内容。这些要点有助于构建更加健壮可靠的基于 Spring 的企业级应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值