Spring注解开发中,如何理解声明式事务及其工作原理?

2026-05-22 08:372阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1252个文字,预计阅读时间需要6分钟。

Spring注解开发中,如何理解声明式事务及其工作原理?

声明式事务使用、基本原理分析+浅析Spring注解开发,声明式事务及原理+浅析Spring注解开发,基于Spring 4.3.12,包含声明式事务使用、基本原理分析+浅析Spring注解开发,自定义注册组件、属性

声明式事务使用、基本原理分析 浅尝Spring注解开发_声明式事务及原理

浅尝Spring注解开发,基于Spring 4.3.12
包含声明式事务使用、基本原理分析

浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
浅尝Spring注解开发_Bean生命周期及执行过程
浅尝Spring注解开发_AOP原理及完整过程分析(源码)
浅尝Spring注解开发_声明式事务及原理
浅尝Spring注解开发_简单理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
Spring注解开发_Spring容器创建概述
浅尝Spring注解开发_Servlet3.0与SpringMVC

声明式事务 环境搭建
  1. 添加依赖:数据源、数据库驱动、Spring-jdbc模块

  2. 业务类

    UserDao

    @Repository public class UserDao { @Autowired private JdbcTemplate jdbcTemplate; public void insert(){ String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?)"; String username = UUID.randomUUID().toString().substring(0, 5); jdbcTemplate.update(sql, username,19); } }

    UserService

    Spring注解开发中,如何理解声明式事务及其工作原理?

    @Service public class UserService { @Autowired private UserDao userDao; public void insertUser(){ userDao.insert(); //otherDao.other();xxx System.out.println("插入完成..."); int i = 10/0; } }

  3. 配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据

    @Configuration public class TxConfig { //数据源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } //jdbcTemplate @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } }

开启注解
  1. 给方法上标注 @Transactional 表示当前方法是一个事务方法

    UserService

    @Service public class UserService { @Autowired private UserDao userDao; @Transactional public void insertUser(){ userDao.insert(); //otherDao.other();xxx System.out.println("插入完成..."); int i = 10/0; } }

  2. @EnableTransactionManagement 开启基于注解的事务管理功能

    @EnableTransactionManagement @Configuration public class TxConfig { //... }

  3. 配置事务管理器来控制事务

    @EnableTransactionManagement @Configuration public class TxConfig { //数据源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } //jdbcTemplate @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } //注册事务管理器在容器中 @Bean public PlatformTransactionManager transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); } }

  4. 测试

    • 出现异常时会回滚,不会插入数据库

    public class IOCTest_Tx { @Test public void test01(){ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class); UserService userService = applicationContext.getBean(UserService.class); userService.insertUser(); applicationContext.close(); } }

原理分析

与AOP相似,注册,包装,增强器,拦截器,执行目标方法
浅尝Spring注解开发_AOP原理及完整过程分析(源码)

  1. 进入@EnableTransactionManagement

    1. 利用TransactionManagementConfigurationSelector给容器中会导入组件,判断AdviceMode的值选择导入哪个组件

      1. 如果是PROXY导入两个组件(默认)

        • AutoProxyRegistrar(自动代理注册器)
        • ProxyTransactionManagementConfiguration(代理事务管理配置)
      2. 如果是ASPECTJ导入

        • TransactionManagementConfigUtils
  2. 分析AutoProxyRegistrar

    1. 用于给容器中注入Bean,调用registerBeanDefinitions()
    2. 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary()最终注册InfrastructureAdvisorAutoProxyCreator(基础架构自动代理创建者)组件,也是后置处理器类型,利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用
    3. 这个类中同时注册了一个AnnotationAwareAspectJAutoProxyCreator(注解装配模式的AspectJ切面自动代理创建器),这个就是在AOP一开始注册的那个类,用于Bean实例化时的后置处理器
  3. 分析ProxyTransactionManagementConfiguration

    1. 给容器中注册事务增强器,如BeanFactoryTransactionAttributeSourceAdvisor(BeanFactory事务属性源增强器)

      1. 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解

      2. 事务拦截器:

        1. TransactionInterceptor(它是一个 MethodInterceptor方法拦截器,和AOP中是相同的):保存了事务属性信息,事务管理器

        2. 在目标方法执行的时候执行拦截器链

        3. 事务拦截器

          1. 先获取事务相关的属性

          2. 再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger

            最终会从容器中按照类型获取一个PlatformTransactionManager

          3. 执行目标方法invokeWithinTransaction(){ invocation.proceedWithInvocation() }

            • 如果异常,获取到事务管理器,利用事务管理回滚操作txInfo.getTransactionManager().rollback()
            • 如果正常,利用事务管理器,提交事务txInfo.getTransactionManager().commit()

本文共计1252个文字,预计阅读时间需要6分钟。

Spring注解开发中,如何理解声明式事务及其工作原理?

声明式事务使用、基本原理分析+浅析Spring注解开发,声明式事务及原理+浅析Spring注解开发,基于Spring 4.3.12,包含声明式事务使用、基本原理分析+浅析Spring注解开发,自定义注册组件、属性

声明式事务使用、基本原理分析 浅尝Spring注解开发_声明式事务及原理

浅尝Spring注解开发,基于Spring 4.3.12
包含声明式事务使用、基本原理分析

浅尝Spring注解开发_自定义注册组件、属性赋值、自动装配
浅尝Spring注解开发_Bean生命周期及执行过程
浅尝Spring注解开发_AOP原理及完整过程分析(源码)
浅尝Spring注解开发_声明式事务及原理
浅尝Spring注解开发_简单理解BeanFactoryPostProcessor、BeanDefinitionRegistryPostProcessor、ApplicationListener
Spring注解开发_Spring容器创建概述
浅尝Spring注解开发_Servlet3.0与SpringMVC

声明式事务 环境搭建
  1. 添加依赖:数据源、数据库驱动、Spring-jdbc模块

  2. 业务类

    UserDao

    @Repository public class UserDao { @Autowired private JdbcTemplate jdbcTemplate; public void insert(){ String sql = "INSERT INTO `tbl_user`(username,age) VALUES(?,?)"; String username = UUID.randomUUID().toString().substring(0, 5); jdbcTemplate.update(sql, username,19); } }

    UserService

    Spring注解开发中,如何理解声明式事务及其工作原理?

    @Service public class UserService { @Autowired private UserDao userDao; public void insertUser(){ userDao.insert(); //otherDao.other();xxx System.out.println("插入完成..."); int i = 10/0; } }

  3. 配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据

    @Configuration public class TxConfig { //数据源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } //jdbcTemplate @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } }

开启注解
  1. 给方法上标注 @Transactional 表示当前方法是一个事务方法

    UserService

    @Service public class UserService { @Autowired private UserDao userDao; @Transactional public void insertUser(){ userDao.insert(); //otherDao.other();xxx System.out.println("插入完成..."); int i = 10/0; } }

  2. @EnableTransactionManagement 开启基于注解的事务管理功能

    @EnableTransactionManagement @Configuration public class TxConfig { //... }

  3. 配置事务管理器来控制事务

    @EnableTransactionManagement @Configuration public class TxConfig { //数据源 @Bean public DataSource dataSource() throws Exception{ ComboPooledDataSource dataSource = new ComboPooledDataSource(); dataSource.setUser("root"); dataSource.setPassword("123456"); dataSource.setDriverClass("com.mysql.jdbc.Driver"); dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return dataSource; } //jdbcTemplate @Bean public JdbcTemplate jdbcTemplate() throws Exception{ //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件 JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource()); return jdbcTemplate; } //注册事务管理器在容器中 @Bean public PlatformTransactionManager transactionManager() throws Exception{ return new DataSourceTransactionManager(dataSource()); } }

  4. 测试

    • 出现异常时会回滚,不会插入数据库

    public class IOCTest_Tx { @Test public void test01(){ AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(TxConfig.class); UserService userService = applicationContext.getBean(UserService.class); userService.insertUser(); applicationContext.close(); } }

原理分析

与AOP相似,注册,包装,增强器,拦截器,执行目标方法
浅尝Spring注解开发_AOP原理及完整过程分析(源码)

  1. 进入@EnableTransactionManagement

    1. 利用TransactionManagementConfigurationSelector给容器中会导入组件,判断AdviceMode的值选择导入哪个组件

      1. 如果是PROXY导入两个组件(默认)

        • AutoProxyRegistrar(自动代理注册器)
        • ProxyTransactionManagementConfiguration(代理事务管理配置)
      2. 如果是ASPECTJ导入

        • TransactionManagementConfigUtils
  2. 分析AutoProxyRegistrar

    1. 用于给容器中注入Bean,调用registerBeanDefinitions()
    2. 调用AopConfigUtils.registerAutoProxyCreatorIfNecessary()最终注册InfrastructureAdvisorAutoProxyCreator(基础架构自动代理创建者)组件,也是后置处理器类型,利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用
    3. 这个类中同时注册了一个AnnotationAwareAspectJAutoProxyCreator(注解装配模式的AspectJ切面自动代理创建器),这个就是在AOP一开始注册的那个类,用于Bean实例化时的后置处理器
  3. 分析ProxyTransactionManagementConfiguration

    1. 给容器中注册事务增强器,如BeanFactoryTransactionAttributeSourceAdvisor(BeanFactory事务属性源增强器)

      1. 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解

      2. 事务拦截器:

        1. TransactionInterceptor(它是一个 MethodInterceptor方法拦截器,和AOP中是相同的):保存了事务属性信息,事务管理器

        2. 在目标方法执行的时候执行拦截器链

        3. 事务拦截器

          1. 先获取事务相关的属性

          2. 再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger

            最终会从容器中按照类型获取一个PlatformTransactionManager

          3. 执行目标方法invokeWithinTransaction(){ invocation.proceedWithInvocation() }

            • 如果异常,获取到事务管理器,利用事务管理回滚操作txInfo.getTransactionManager().rollback()
            • 如果正常,利用事务管理器,提交事务txInfo.getTransactionManager().commit()