目录

spring注解驱动之声明式事务

使用声明式事务步骤

引入相关依赖

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-jdbc</artifactId>
   <version>4.3.12.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
<dependency>
   <groupId>c3p0</groupId>
   <artifactId>c3p0</artifactId>
   <version>0.9.1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.44</version>
</dependency>

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
@EnableTransactionManagement
@ComponentScan("com.eh.tx")
@Configuration
public class TxConfig {

    //数据源
    @Bean
    public DataSource dataSource() throws Exception {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setUser("root");
        dataSource.setPassword("333");
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/db01");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() throws Exception {
        //Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
        return jdbcTemplate;
    }

    //注册事务管理器在容器中
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }
}

给方法上标注 @Transactional 表示当前方法是一个事务方法;

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Service
public class UserService {
   
   @Autowired
   private UserDao userDao;
   
   @Transactional
   public void insertUser(){
      userDao.insert();
      //otherDao.other();xxx
      System.out.println("插入完成...");
      int i = 10/0;
   }
}

@EnableTransactionManagement 开启基于注解的事务管理功能;同配置文件中tx-driven

1
2
3
4
@EnableTransactionManagement
@ComponentScan("com.eh.tx")
@Configuration
public class TxConfig {

配置事务管理器来控制事务;

1
2
3
4
5
 //注册事务管理器在容器中
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) throws Exception {
        return new DataSourceTransactionManager(dataSource);
    }

声明式事务源码分析

声明式事务运行机制与aop大同小异,下面就来分析一波

首先还是从@EnableTransactionManagement着手

  1. @EnableTransactionManagement

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(TransactionManagementConfigurationSelector.class)
    public @interface EnableTransactionManagement {
       
       boolean proxyTargetClass() default false;
       
       AdviceMode mode() default AdviceMode.PROXY;
       
       int order() default Ordered.LOWEST_PRECEDENCE;
       
    }
    

    可以看到这个注解使用TransactionManagementConfigurationSelector给容器中注册组件

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    @Override
    protected String[] selectImports(AdviceMode adviceMode) {
       switch (adviceMode) {
          case PROXY:
             return new String[] {AutoProxyRegistrar.class.getName(),
                   ProxyTransactionManagementConfiguration.class.getName()};
          case ASPECTJ:
             return new String[] {determineTransactionAspectClass()};
          default:
             return null;
       }
    }
    

    由于默认adviceMode是PROXY,所以导入了以下两个组件:

    • AutoProxyRegistrar
    • ProxyTransactionManagementConfiguration
  2. AutoProxyRegistrar

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
      @Override
     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
         boolean candidateFound = false;
        // 获取配置类的所有注解信息
         Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
         for (String annType : annTypes) {
          // 获取EnableTransactionManagement注解的属性值
             AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
             if (candidate == null) {
                 continue;
             }
             Object mode = candidate.get("mode");
             Object proxyTargetClass = candidate.get("proxyTargetClass");
             if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
                     Boolean.class == proxyTargetClass.getClass()) {
                 candidateFound = true;
                 if (mode == AdviceMode.PROXY) {
              // 给容器中注册一个InfrastructureAdvisorAutoProxyCreator组件
                     AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                     if ((Boolean) proxyTargetClass) {
                         AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                         return;
                     }
                 }
             }
         }
        ...
     }
       
    

    InfrastructureAdvisorAutoProxyCreator这个组件做的事情跟aop中的AnnotationAwareAspectJAutoProxyCreator很类似, 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(包含增强器),代理对象执行方法利用拦截器链进行调用;

    http://img.cana.space/picStore/20201029231738.png

    代理对象中的增强器由下面这个组件注入到容器中

  3. ProxyTransactionManagementConfiguration

    作用:给容器中注册事务增强器

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    
    @Configuration(proxyBeanMethods = false)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
       
       @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
       @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
       public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
             TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
       
          BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
          advisor.setTransactionAttributeSource(transactionAttributeSource);
          advisor.setAdvice(transactionInterceptor);
          if (this.enableTx != null) {
             advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
          }
          return advisor;
       }
       
      // 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
       @Bean
       @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
       public TransactionAttributeSource transactionAttributeSource() {
          return new AnnotationTransactionAttributeSource();
       }
       
      /*
      事务拦截器:
     TransactionInterceptor;保存了事务属性信息,事务管理器;
     他是一个 MethodInterceptor;
     在目标方法执行的时候执行拦截器链;
     事务拦截器:
     1)、先获取事务相关的属性
     2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger
     最终会从容器中按照类型获取一个PlatformTransactionManager;
    3)、执行目标方法
    如果异常,获取到事务管理器,利用事务管理回滚操作;
    如果正常,利用事务管理器,提交事务
      */
       @Bean
       @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
       public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
          TransactionInterceptor interceptor = new TransactionInterceptor();
          interceptor.setTransactionAttributeSource(transactionAttributeSource);
          if (this.txManager != null) {
             interceptor.setTransactionManager(this.txManager);
          }
          return interceptor;
       }
       
    }