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,这样切面类就能为目标业务类提供事务管理功能。

集成特定的应用服务器

posted @ 2022-06-17 22:02  EA2218764AB  阅读(93)  评论(0编辑  收藏  举报