2

【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置

 2 years ago
source link: https://blog.51cto.com/laowang6/5577107
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置

原创

一个数据源的事物管理配置 与 多数据源的事物管理配置

大多数 Spring 应用程序只有一个数据源,只需要一个事务管理器(TransactionManager)。
但是在多个数据源的情况下,我们就需要在一个应用程序中配置多个独立的事务管理器。
我们可以通过 @Transactional 的 value 或 transactionManager 属性来指定让哪个 TransactionManager 生效。

 https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#tx-multiple-tx-mgrs-with-attransactional

那么,一个数据源 与 多数据源的事物管理配置有什么不同呢?

事物管理相关的几个核心概念有:DataSource、TransactionManager 和 TransactionInterceptor。

  • DataSource
    DataSource 是用来获取 DB 连接的。

  • TransactionManager
    用来管理事物,核心的接口有 PlatformTransactionManager,它可以获取连接、提交/回滚事物。

  • TransactionInterceptor
    它是 spring-tx 用来实现声明式事物管理的核心类,它会对事物方法进行拦截,然后实现事物的操作(提交/回滚事物)。

所以,我们在进行 spring 的事物管理配置的时候,这三个重要的角色都需要参与进来:DataSource、TransactionManager 和 TransactionInterceptor。

单个数据源的事物管理配置

可能你会说 Spring 开启事物管理不就是使用一个 @EnableTransactionManagement 就搞定了吗?确实也是这样。
仔细想想,我们不禁会有疑问:
1、@EnableTransactionManagement 能开启事物管理的原理是什么呢?
2、如果没有 @EnableTransactionManagement,我们自己配置事物管理的话,应当如何配置呢?

手动进行事物管理配置

我们先来看一下,如果没有使用 @EnableTransactionManagement 的情况下,应该如何来进行事物管理的配置?

如果使用 MyBatis 来操作数据库的话,手动进行事物管理的配置可以分为四个步骤进行:

  • 1、定义数据源 DataSource
  • 2、定义基于 DataSource 的 TransactionManager(事物管理器)
  • 3、定义 Advisor 来拦截 @Transactional 方法(主要是让 Advice:TransactionInterceptor 生效)
  • 4、定义基于 DataSource 的 SqlSessionFactory(通过 MyBatis 来操作 sql)
@Configuration
@MapperScan(basePackages = "com.kvn.mapper.biz", sqlSessionFactoryRef = "bizSqlSessionFactory")
public class MasterMybatisConfig {

    @Bean("biz")
    @ConfigurationProperties(prefix = "spring.datasource.biz")
    public DataSource bizDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    /**
     * 创建 biz 数据源的事物管理器
     */
    @Bean(name = "bizTxManager")
    public PlatformTransactionManager bizTxManager(@Qualifier("biz") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean("bizSqlSessionFactory")
    public SqlSessionFactory bizSqlSessionFactory(@Qualifier("biz") DataSource dataSource) throws Exception {
      // 设置数据源
      SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
      sqlSessionFactoryBean.setDataSource(dataSource);
      //mapper的xml文件位置
      PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
      String locationPattern = "classpath*:/mapper/biz/*.xml";
      sqlSessionFactoryBean.setMapperLocations(resolver.getResources(locationPattern));
      //对应数据库的entity位置
      String typeAliasesPackage = "com.kvn.entity.biz";
      sqlSessionFactoryBean.setTypeAliasesPackage(typeAliasesPackage);
      return sqlSessionFactoryBean.getObject();
    }

    @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
      TransactionInterceptor interceptor = new TransactionInterceptor();
      TransactionAttributeSource transactionAttributeSource = new AnnotationTransactionAttributeSource();
      interceptor.setTransactionAttributeSource(transactionAttributeSource);
      
      // 定义 Advisor --> Pointcut + Advice
      BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
      advisor.setTransactionAttributeSource(transactionAttributeSource); // 供 Pointcut 使用
      advisor.setAdvice(interceptor); // Advice  
      return advisor;
    }
}

注意:如果我们不需要对数据源进行事物管理的话,可以不配置 transactionAdvisor

@EnableTransactionManagement 开启事物管理的原理

在一个只有一个数据源的 SpringBoot 工程中,我们只需要配置一个 @EnableTransactionManagement 就能开启事物管理,让 @Transactional 生效,这是为什么呢?
使用 @EnableTransactionManagement 之后,SpringBoot 为我们配置哪些 bean 来支持事物管理呢?

@EnableTransactionManagement 的作用

查看 @EnableTransactionManagement 的源码,我们可以发现它帮我们注册了 BeanFactoryTransactionAttributeSourceAdvisor,也就是让 TransactionInterceptor 来拦截 @Transactional 标记的方法
但是 @EnableTransactionManagement 并没有帮我们注册 TransactionManagerDataSource

那么,TransactionManagerDataSource 是如何自动注册的呢?
SpringBoot 会帮我们默认注册一个 HikariDataSource

【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置_spring

当只有一个 DataSource 时,SpringBoot 会默认帮我们注册一个 TransactionManager

【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置_事物管理_02

可以看到,如果我们的工程中只有一个数据源的话,SpringBoot 就会帮我们自动注册一个 TransactionManagerHikariDataSource

@EnableTransactionManagement 的作用是负责注册必要的 Spring 组件,比如:BeanFactoryTransactionAttributeSourceAdvisorTransactionInterceptor,这些组件为注释驱动的事务管理提供了动力和支持。

  • BeanFactoryTransactionAttributeSourceAdvisor
    BeanFactoryTransactionAttributeSourceAdvisor 实现了 PointcutAdvisor 接口,它持有的 Pointcut 决定了匹配 @Transactional 注解标记的方法;
    它持有的 Advice,即 TransactionInterceptor,实现了具体的事物拦截逻辑。
  • TransactionInterceptor
    TransactionInterceptor 在做事物方法拦截时,会去决定使用哪个 TransactionManager,即 TransactionAspectSupport.determineTransactionManager() 方法实现的功能。

多个数据源的事物管理配置

从上面对单个数据源的事物管理配置的研究,我们可以发现 @EnableTransactionManagement 的作用就是帮我们自动注册 BeanFactoryTransactionAttributeSourceAdvisor 来支持对 @Transactoinal 方法的拦截。
TransactionManagerDataSource 是需要另外进行配置的。当工程中只有一个数据源的情况下,SpringBoot 又会默认帮我们注册 TransactionManagerDataSource ,所以,在只有一个数据源的情况下,我们通过 @EnableTransactionManagement 注解就能顺利的通过 spring-tx 来管理事物。

当工程中有多个数据源的时候(>=2),我们依然可以通过 @EnableTransactionManagement 来自动注册 BeanFactoryTransactionAttributeSourceAdvisor,但是 SpringBoot 就不会自动注册 TransactionManagerDataSource 了,而需要我们手动进行配置。

所以,配置 n 个数据源的事物管理的步骤如下:
1、通过 @EnableTransactionManagement 来开启对 @Transactional 方法的拦截
2、定义 n 个数据源 DataSource
3、定义基于 DataSource 的 TransactionManager(事物管理器)
4、定义基于 DataSource 的 SqlSessionFactory (通过 MyBatis 操作 sql)

手动配置 2 个数据源的例子:

  • 定义 master 数据源 & 事物管理器

    【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置_事物管理_03
  • 定义 slave 数据源 & 事物管理器

    【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置_spring_04
  • 数据源的 properties 配置

    【老王读Spring Transaction-7】一个数据源的事物管理配置 与 多数据源的事物管理配置_事物管理_05

注意:多数据源的情况下,需要使用类似 @Transactional("masterTxManager") 来指定事物方法使用的事物管理器是哪个。

配置 spring 的事物管理,大体分为三个步骤:(单数据源 与 多数据源 都是如此)

  • 1、定义数据源 DataSource
  • 2、定义基于 DataSource 的 TransactionManager(事物管理器)
  • 3、定义 Advisor 来拦截 @Transactional 方法(主要是让 Advice:TransactionInterceptor 生效)

不管是一个数据源,还是多个数据源,都是上面的套路。
一个数据源的配置 与 多个数据源的配置 的不同是:如果工程中只需要一个数据源,那么 SpringBoot 可以为我们做到全自动的配置,只需要使用 @EnableTransactionManagement 就可以使用 spring 的事物管理。


SpringBoot 能自动配置单个数据源的事物管理的原理是:
1、spring-boot-autoconfigure.jar 中的 DataSourcePoolMetadataProvidersConfiguration 类会帮我们自动注册 HikariDataSource
2、spring-boot-autoconfigure.jar 中的 DataSourceTransactionManagerAutoConfiguration 类会帮我们自动注册 TransactionManager
3、@EnableTransactionManagement 会注册 Advisor: BeanFactoryTransactionAttributeSourceAdvisor

如果是多数据源进行事物管理配置的话,步骤如下:

  • 1、手动定义 n 个 DataSource
  • 2、手动定义基于 DataSource 的 TransactionManager(事物管理器)
  • 3、添加 @EnableTransactionManagement 来开启对 @Transactional 方法的拦截
  • 收藏
  • 评论
  • 分享
  • 举报

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK