Spring 注解事物@Transactional开发和源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

Spring 注解 事物开发

一、声明式事务:

环境搭建: 1、导入相关依赖 数据源、数据库驱动、Spring-jdbc模块

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>4.3.13.RELEASE</version>
    </dependency>
    ​
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.44</version>
    </dependency>

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

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

    @Transactional
    public void add() {
        deptDao.insert();
        int i=10/0;
    }

4、 @EnableTransactionManagement 开启基于注解的事务管理功能; @EnableXXX 5、配置事务管理器来控制事务; @Bean public PlatformTransactionManager transactionManager()

代码:

    package com.willow.tx;
    ​
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.jdbc.core.JdbcTemplate;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.jdbc.datasource.DriverManagerDataSource;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    ​
    import javax.sql.DataSource;
    ​
    @Configuration
    @EnableTransactionManagement
    @ComponentScan("com.willow.tx")
    public class TxConfig {
    ​
    ​
        @Bean
        public DataSource dataSource(){
            DriverManagerDataSource ds = new DriverManagerDataSource ();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://192.168.7.108/willow");
            ds.setUsername("root");
            ds.setPassword("123456");
            return ds;
        }
    ​
        @Bean
        public JdbcTemplate jdbcTemplate(){
            return  new JdbcTemplate(dataSource());
        }
    ​
        @Bean
        public PlatformTransactionManager transactionManager(){
           return new DataSourceTransactionManager(dataSource());
        }
    ​
    }
    ​

二、事物原理部分

1)、@EnableTransactionManagement注解

    @Import(TransactionManagementConfigurationSelector.class)

利用TransactionManagementConfigurationSelector给容器中会导入下面两个组件

  • AutoProxyRegistrar
  • ProxyTransactionManagementConfiguration

        public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
         @Override
         protected String[] selectImports(AdviceMode adviceMode) {
        //AdviceMode在 EnableTransactionManagement注解中 默认为AdviceMode mode() default AdviceMode.PROXY;
          switch (adviceMode) {
           case PROXY:
            return new String[] {AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
           case ASPECTJ:
            return new String[] {TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
           default:
            return null;
          }
         }
        ​
        }

2)、AutoProxyRegistrar:

给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件

    1.  AutoProxyRegistrar.registerBeanDefinitions() -->
        
    2.  AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);   -->
        
    3.    public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
      return registerAutoProxyCreatorIfNecessary(registry, null);
     }
    ​
    4.public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
      return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);  //注册了一个InfrastructureAdvisorAutoProxyCreator组件
    }
  • InfrastructureAdvisorAutoProxyCreator:?原理和AOP部分的AnnotationAwareAspectJAutoProxyCreator一样,利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;

3)、ProxyTransactionManagementConfiguration 做了什么?

3.1 、给容器中注册事务增强器;

3.1.1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
    @Configuration
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    ​
        //事物增强器
     @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
     public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
      BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
      advisor.setTransactionAttributeSource(transactionAttributeSource());
      advisor.setAdvice(transactionInterceptor());
      advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
      return advisor;
     }
    ​
     @Bean
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
     public TransactionAttributeSource transactionAttributeSource() {
      return new AnnotationTransactionAttributeSource();
     }
       // 2)、事务拦截器:
       // TransactionInterceptor;保存了事务属性信息,事务管理器;他是一个 MethodInterceptor;
        @Bean
     @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
     public TransactionInterceptor transactionInterceptor() {
      TransactionInterceptor interceptor = new TransactionInterceptor();
      interceptor.setTransactionAttributeSource(transactionAttributeSource());
      if (this.txManager != null) {
       interceptor.setTransactionManager(this.txManager);
      }
      return interceptor;
     }
    }
3.1.2)、事务拦截器:

MethodInterceptor在目标方法执行的时候;

执行拦截器链;

事务拦截器:

1)、先获取事务相关的属性

2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger最终会从容器中按照类型获取一个PlatformTransactionManager;

3)、执行目标方法

如果异常,获取到事务管理器,利用事务管理回滚操作;

如果正常,利用事务管理器,提交事务

3.1.2.1 MethodInterceptor在目标方法执行的时候;

TransactionInterceptor.invoke() 方法

    @Override
    public Object invoke(final MethodInvocation invocation) throws Throwable {
       
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    ​
       
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
          @Override
          public Object proceedWithInvocation() throws Throwable {
             return invocation.proceed();
          }
       });
    }
3.1.2.2 TransactionAspectSupport.invokeWithinTransaction()方法
    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
          throws Throwable {
    ​
       // 1)、先获取事务相关的属性
       final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
       // 2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger
       final PlatformTransactionManager tm = determineTransactionManager(txAttr);
        //获取要执行的事物方法
       final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    ​
       if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
          // 创建一个事物
          TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
          Object retVal = null;
          try {
             //事物方法的执行
             retVal = invocation.proceedWithInvocation();
          }
          catch (Throwable ex) {
             // 有异常回滚事物
             completeTransactionAfterThrowing(txInfo, ex);
             throw ex;
          }
          finally {
             cleanupTransactionInfo(txInfo);
          }
           //得到事物管理器,提交事物
          commitTransactionAfterReturning(txInfo);
          return retVal;
       }
    ​
       else {
          final ThrowableHolder throwableHolder = new ThrowableHolder();
    ​
          // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
          try {
             Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
                   new TransactionCallback<Object>() {
                      @Override
                      public Object doInTransaction(TransactionStatus status) {
                         TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
                         try {
                            return invocation.proceedWithInvocation();
                         }
                         catch (Throwable ex) {
                            if (txAttr.rollbackOn(ex)) {
                               // A RuntimeException: will lead to a rollback.
                               if (ex instanceof RuntimeException) {
                                  throw (RuntimeException) ex;
                               }
                               else {
                                  throw new ThrowableHolderException(ex);
                               }
                            }
                            else {
                               // A normal return value: will lead to a commit.
                               throwableHolder.throwable = ex;
                               return null;
                            }
                         }
                         finally {
                            cleanupTransactionInfo(txInfo);
                         }
                      }
                   });
    ​
             // Check result state: It might indicate a Throwable to rethrow.
             if (throwableHolder.throwable != null) {
                throw throwableHolder.throwable;
             }
             return result;
          }
          catch (ThrowableHolderException ex) {
             throw ex.getCause();
          }
          catch (TransactionSystemException ex2) {
             if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
                ex2.initApplicationException(throwableHolder.throwable);
             }
             throw ex2;
          }
          catch (Throwable ex2) {
             if (throwableHolder.throwable != null) {
                logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
             }
             throw ex2;
          }
       }
    }
3.1.2.2.1)、获取PlatformTransactionManager

如果事先没有添加指定任何transactionmanger最终会从容器中按照类型获取一个PlatformTransactionManager

    protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
       // Do not attempt to lookup tx manager if no tx attributes are set
       if (txAttr == null || this.beanFactory == null) {
          return getTransactionManager();
       }
       //判断是否@Transactional(transactionManager = "")指定了transactionManager
       String qualifier = txAttr.getQualifier();
       if (StringUtils.hasText(qualifier)) {
          return determineQualifiedTransactionManager(qualifier);
       }
       else if (StringUtils.hasText(this.transactionManagerBeanName)) {
          return determineQualifiedTransactionManager(this.transactionManagerBeanName);
       }
       else {
          PlatformTransactionManager defaultTransactionManager = getTransactionManager();
          if (defaultTransactionManager == null) {
             defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
             if (defaultTransactionManager == null) {
                defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
                 //在IOC容器中获取PlatformTransactionManager
                this.transactionManagerCache.putIfAbsent(
                      DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
             }
          }
          return defaultTransactionManager;
       }
    }

来源:[]()

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring 注解事物@Transactional开发和源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏