千家信息网

Spring框架中注解配置事务控制的示例分析

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,这篇文章主要为大家展示了"Spring框架中注解配置事务控制的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Spring框架中注解配置事务控制的示
千家信息网最后更新 2026年11月04日Spring框架中注解配置事务控制的示例分析

这篇文章主要为大家展示了"Spring框架中注解配置事务控制的示例分析",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"Spring框架中注解配置事务控制的示例分析"这篇文章吧。

基于注解的事务控制

基于注解配置事务控制,相较XML配置来说更加简单,但仍需要XML提供依赖,不能完全摆脱XML。前期准备工作和XML配置大同小异,这里不做赘述,建议学习基于注解配置前先学习XML配置事务控制。

这里给出本次测试的全部XML配置,具体细节在后面依次介绍。

                                                                                                                                                                                                                                                                                                                                

1.配置事务管理器

       

2.在业务层使用@Transactional 注解

只需要在业务层实现类上加上@Transactional即可。

该注解的属性和 xml 中的属性含义一致。该注解可以出现在接口上,类上和方法上。

  • 出现接口上,表示该接口的所有实现类都有事务支持。

  • 出现在类上,表示类中所有方法有事务支持

  • 出现在方法上,表示方法有事务支持。

  • 以上三个位置的优先级:方法>类>接口

package com.gql.service;import java.util.List;import org.springframework.transaction.annotation.Transactional;import com.gql.dao.UserDao;import com.gql.entity.User;/** * 类说明: *         业务层实现类 * @guoqianliang1998. */@Transactionalpublic class UserServiceImp implements UserService {        private UserDao userDao;                public void setUserDao(UserDao userDao) {                this.userDao = userDao;        }        @Override        public void save(User user) {                userDao.save(user);                int i = 1/0;        }        @Override        public void update(int id, User user) {                userDao.update(id, user);        }        @Override        public void delete(int id) {                userDao.delete(id);        }        @Override        public User getUser(int id) {                User user = userDao.getUser(id);                return user;        }        @Override        public List getUserList(int[] ids) {                List userList = userDao.getUserList(ids);                return userList;        }        @Override        public List getUserList() {                List list = userDao.getUserList();                return list;        }}

3.开启 spring 对注解事务的支持

 

4.注解扫描器

 

Spring 注解事务实现机制

1.事务的实现机制

AOP动态代理进行方法拦截

在应用系统调用声明@Transactional 的目标方法时,Spring Framework 默认使用 AOP 代理,在代码运行时生成一个代理对象,根据@Transactional 的属性配置信息,这个代理对象决定该声明@Transactional 的目标方法是否由拦截器 TransactionInterceptor 来使用拦截。

在 TransactionInterceptor 拦截时,会在在目标方法开始执行之前创建并加入事务,并执行目标方法的逻辑, 最后根据执行情况是否出现异常,利用抽象事务管理器AbstractPlatformTransactionManager 操作数据源 DataSource 提交或回滚事务, 如下图所示。

注:上面两个xxxServiceImpl,表示的是同一个service的调用,前面用虚线,表示欲调用该service的方法,进入该service的方法前经历了aop进行拦截,然后才真正进入该service方法(后面的实线表示的service)

Spring AOP 代理有 CglibAopProxy 和 JdkDynamicAopProxy 两种,上图是以 CglibAopProxy 为例

  • 对于 CglibAopProxy,需要调用其内部类的 DynamicAdvisedInterceptor 的 intercept 方法。

  • 对于 JdkDynamicAopProxy,需要调用其 invoke 方法。

事务管理器进行事务提交或回滚

事务管理的框架是由抽象事务管理器 AbstractPlatformTransactionManager 来提供的,而具体的底层事务处理实现,由 PlatformTransactionManager 的具体实现类来实现,如事务管理器 DataSourceTransactionManager。

不同的事务管理器管理不同的数据资源 DataSource,比如 DataSourceTransactionManager 管理 JDBC 的 Connection。

PlatformTransactionManager,AbstractPlatformTransactionManager 及具体实现类关系如图 2 所示。

2.注解方式的事务使用注意事项

当您对 Spring 的基于注解方式的实现步骤和事务内在实现机制有较好的理解之后,就会更好的使用注解方式的事务管理,避免当系统抛出异常,数据不能回滚的问题。

正确的设置 @Transactional 的 propagation 属性(熟知事务的传播特性)

需要注意下面三种 propagation 可以不启动事务。本来期望目标方法进行事务管理,但若是错误的配置这三种 propagation,事务将不会发生回滚。

  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

正确的设置 @Transactional 的 rollbackFor 属性

默认情况下,如果在事务中抛出了未检查异常(继承自 RuntimeException 的异常)或者 Error,则 Spring 将回滚事务;除此之外,Spring 不会回滚事务。

如果在事务中抛出其他类型的异常,并期望 Spring 能够回滚事务,可以指定 rollbackFor。

例:@Transactional(propagation= Propagation.REQUIRED,rollbackFor= MyException.class)

通过分析 Spring 源码可以知道,若在目标方法中抛出的异常是 rollbackFor 指定的异常的子类,事务同样会回滚。

清单 3. RollbackRuleAttribute 的 getDepth 方法

private int getDepth(Class exceptionClass, int depth) {        if (exceptionClass.getName().contains(this.exceptionName)) {            // Found it!            return depth;}        // If we've gone as far as we can go and haven't found it...        if (exceptionClass == Throwable.class) {            return -1;}return getDepth(exceptionClass.getSuperclass(), depth + 1);}

@Transactional 只能应用到 public 方法才有效

只有@Transactional 注解应用到 public 方法,才能进行事务管理。

这是因为在使用 Spring AOP 代理时,Spring 在调用TransactionInterceptor 在目标方法执行前后进行拦截之前,DynamicAdvisedInterceptor(CglibAopProxy 的内部类)的intercept 方法或 JdkDynamicAopProxy 的 invoke 方法会间接调用 AbstractFallbackTransactionAttributeSource(Spring 通过这个类获取@Transactional 注解的事务属性配置属性信息)的 computeTransactionAttribute 方法。

AbstractFallbackTransactionAttributeSource

protected TransactionAttribute computeTransactionAttribute(Method method,    Class targetClass) {        // Don't allow no-public methods as required.        if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {return null;}

allowPublicMethodsOnly方法由子类AnnotationTransactionAttributeSource实现,该子类方法中默认是true,所以当你加了事务注解的方法不是public时,该方法直接返回null

不会获取@Transactional 的属性配置信息,最终会造成不会用 TransactionInterceptor 来拦截该目标方法进行事务管理。

避免 Spring 的 AOP 的自调用问题,必须要跨service调用

在 Spring 的 AOP 代理下,只有目标方法由外部调用(也就是跨service调用),目标方法才由 Spring 生成的代理对象来管理,这会造成自调用问题。

若同一类中的其他没有@Transactional 注解的方法内部调用有@Transactional 注解的方法,有@Transactional 注解的方法的事务被忽略,不会发生回滚。

示例:

-->@Servicepublic class OrderService {     private void insert() {        insertOrder();    }        @Transactional    public void insertOrder() {        //insert log info        //insertOrder        //updateAccount    }}

insertOrder 尽管有@Transactional 注解,但它被内部方法 insert 调用,事务被忽略,出现异常事务不会发生回滚。

事务的传播问题PROPAGATION_REQUIRES_NEW只有在跨service时才会有效(也是上面自调用引起的)

class ServiceA{  @Transactional(rollbackFor = Exception.class)  public methodA1(){     ......     //该方式,methodA2上的事务注解不起作用,不会开启新的事务,methodA2与methodA1中的数据一起提交或回滚     1.this.methodA2();     //该方式,methodB1上的事务会启作用     2.ServiceB.methodB1()     ......  };  @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)  public methodA2(){     ......  };} class ServiceB{  @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)  public methodB1(){     ......  };  }

原因在于,跨Service调用方法时,都会经过org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor.intercept()方法,只有经过此处,才能对事务进行控制。

以上是"Spring框架中注解配置事务控制的示例分析"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

事务 方法 注解 配置 管理 事务管理 目标 属性 方式 代理 控制 框架 示例 分析 只有 接口 数据 问题 学习 支持 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 互联网新科技 华服互联网科技怎么样 互联网巨头科技公司 互联网下的科技发展 互联网科技开发公司 未来的互联网科技 碳银互联网科技有限公司 互联网科技宣传片 滨湖区互联网智能科技产品供应 互联网系的金融科技公司 华夏恒生互联网科技013171 工业互联网等科技实现智能化赋能 互联网企业科技类企业如何做账 领航科技大厦互联网公司 神州科技互联网有限公司 福建互联网展示科技馆设计 科技信息时代互联网发展 北京军民互联网科技公司 科技互联网专业工作会议发言稿 武汉亿视互联网科技有限公司 互联网科技行业发展 互联网通讯科技 智能科技公司是互联网公司吗 互联网 的科技创新 银优互联网科技有限公司 互联网科技公司的市场部门 科技赋能互联网健康 广州慧亚互联网科技怎么样 字节跳动和互联网科技 锡山区互联网智能科技产品供应
0