web后端-Spring的事务管理
参考资料
- 精通Spring 4.x 企业应用开发实战
缺失部分待补
数据库事务基础知识
ThreadLocal基础知识
Spring对事务管理的支持
编程式的事务管理
使用XML配置声明式事务
使用注解配置声明式事务
除了基于XML的事务配置,Spring 还提供了基于注解的事务配置,即通过@Transactional对需要事务增强的Bean 接口、实现类或方法进行标注;在容器中配置基于注解的事务增强驱动,即可启用基于注解的声明式事务。笔者在实际项目中一般采用这种配置方式。
使用@Transactional注解
顺着原来的思路,使用@Transactional对基于aop/tx命名空间的事务配置进行改造,比较二者在使用方式上的差异,如代码清单11-16所示。
因为注解本身具有一组普适性的默认事务属性,所以往往只要在需要事务管理的业务类中添加一个@Transactional注解,就完成了业务类事务属性的配置。
当然,注解只提供元数据,它本身并不能完成事务切面织入的功能。因此,还需要在Spring配置文件中通过一行小小的配置“通知”Spring容器对标注@Transactional注解的 Bean进行加工处理,如代码清单11-17所示。
在默认情况下,<tx:annotation-driven>会自动使用名为“transactionManager"的事务管理器。所以,如果用户的事务管理器id为“transactionManager”,则可以进一步将①处的配置简化为“<tx:annotation-driven/>”。
<tx:annotation-driven>还有另外两个属性:
- proxy-target-class:如果为true,则 Spring 将通过创建子类来代理业务类;如果为false,则使用基于接口的代理。如果使用子类代理,则需要在类路径中添加CGLib.jar类库。
- order:如果业务类除事务切面外,还需要织入其他的切面,则通过该属性可以控制事务切面在目标连接点的织入顺序。
关于@Transactional 的属性
基于@Transactional注解的配置和基于XML 的配置方式一样,它拥有一组普适性很强的默认事务属性,往往可以直接使用这些默认的属性。
- 事务传播行为:PROPAGATION_REQUIRED。
- 事务隔离级别:ISOLATION_ DEFAULT。
- 超时时间:依赖于底层的事务系统的默认值。
- 回滚设置:任何运行期异常引发回滚,任何检查型异常不会引发回滚。
因为这些默认设置在大多数情况下都是适用的,所以一般不需要手工设置事务注解的属性(见表11-7)。当然,Spring 允许通过手工设定属性值覆盖默认值。
在何处标注@Transactional注解
@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的public方法上。
但Spring建议在业务实现类上使用@Transactional注解。当然也可以在业务接口上使用@Transactional注解,但这样会留下一些容易被忽视的隐患。因为注解不能被继承,所以在业务接口中标注的@Transactional注解不会被业务实现类继承。如果通过以下配置启用子类代理:
<tx :annotation-driven transaction-manager="txManager" proxy-target-class="true" >
那么业务类不会添加事务增强,照样工作在非事务环境下。举一个具体的实例:如果使用子类代理,假设用户为 BbtForum接口标注了@Transactional注解,那么其实现类BbtForumImpl依旧不会启用事务机制。
因此,Spring建议在具体业务类上使用@Transactional 注解。这样,不管<tx:annotation-driven>将proxy-target-class属性配置为 true或false,业务类都会启用事务机制。
在方法处使用注解
方法处的注解会覆盖类定义处的注解。如果有些方法需要使用特殊的事务属性,则可以在类注解的基础上提供方法注解,如下:
②处的方法注解提供了readOnly事务属性的设置,它将覆盖类级注解中默认的readOnly=false 设置。
使用不同的事务管理器
一般情况下,一个应用仅需使用一个事务管理器。如果希望在不同的地方使用不同的事务管理器,则可以通过如下方式实现:
而topic和 forum的事务管理器可以在XML中分别定义,如下:
在①处,为事务管理器指定了一个数据源,每个事务管理器都可以绑定一个独立的数据源。在②处,指定了一个可被@Transactional注解引用的事务管理器标识。
在一两处使用带标识的@Transactional 注解也许是合适的,但是如果到处都使用,则显得比较啰唆。可以自定义一个绑定到特定事务管理器的注解,然后直接使用这个自定义的注解进行标识,如下:
按相似的方法,还可以定义一个绑定到topic事务管理器的@TopicTransactional注解。完成定义后,就可以用以下方式对原来的代码进行调整:
通过AspectJ LTW引入事务切面
Spring还提供了对AspectJ切面的支持。在 org.springframework.aspects-{version}.jar中有一个用 AspectJ语法编写的 AnnotationTransactionAspect切面类,用于为使用了@Transactional注解的业务类提供事务增强。
使用-javaagent: D:lmasterSpringlspringldistlorg.springframework.aspects-{version}.jar的JVM参数,在类路径META-INF目录下提供如下AspectJ配置文件:
在类加载期,对标注@Transactional注解的类织入AnnotationTransactionAspect事务增强切面。
由于AnnotationTransactionAspect切面类需要使用事务管理器,所以必须利用SpringIoC为切面类提供事务管理器的注入,如下:
如①处所示,通过transactionManager属性注入事务管理器Bean,这样切面类就能为目标业务类提供事务管理功能。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)