栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring事务处理原理步骤详解

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring事务处理原理步骤详解

1、事务处理实现

实现步骤:

* 声明式事务:
*
* 环境搭建:
* 1、导入相关依赖
* 数据源、数据库驱动、Spring-jdbc模块
* 2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
* 3、给方法上标注 @Transactional 表示当前方法是一个事务方法;
* 4、 @EnableTransactionManagement 开启基于注解的事务管理功能;
* @EnableXXX
* 5、配置事务管理器来控制事务;
* @Bean
* public PlatformTransactionManager transactionManager()

代码实现:

@EnableTransactionManagement
@ComponentScan("com.atguigu.tx")
@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;
  }
   
  @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());
  }
} 

2、事务处理原理

原理分析:

* 原理:
* 1)、@EnableTransactionManagement
* 利用TransactionManagementConfigurationSelector给容器中会导入组件
* 导入两个组件
* AutoProxyRegistrar
* ProxyTransactionManagementConfiguration
* 2)、AutoProxyRegistrar:
* 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;
* InfrastructureAdvisorAutoProxyCreator:?
* 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
*
* 3)、ProxyTransactionManagementConfiguration 做了什么?
* 1、给容器中注册事务增强器;
* 1)、事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
* 2)、事务拦截器:
* TransactionInterceptor;保存了事务属性信息,事务管理器;
* 他是一个 MethodInterceptor;
* 在目标方法执行的时候;
* 执行拦截器链;
* 事务拦截器:
* 1)、先获取事务相关的属性
* 2)、再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger
* 最终会从容器中按照类型获取一个PlatformTransactionManager;
* 3)、执行目标方法
* 如果异常,获取到事务管理器,利用事务管理回滚操作;
* 如果正常,利用事务管理器,提交事务
*
*/

核心代码

1、EnableTransactionManagement注解,注入TransactionManagementConfigurationSelector类

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@documented
@import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

2、TransactionManagementConfigurationSelector类,最终会导入AutoProxyRegistrar.class和ProxyTransactionManagementConfiguration.class两个组件。

public class TransactionManagementConfigurationSelector extends AdviceModeimportSelector {
 
  
  @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;
    }
  }
 
  private String determineTransactionAspectClass() {
    return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
 TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
 TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
  }
 
}

3、AutoProxyRegistrar类的作用为:

  给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;

  最终的目的是:利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;

@Override
  public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
    boolean candidateFound = false;
    Set annTypes = importingClassmetadata.getAnnotationTypes();
    for (String annType : annTypes) {
      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) {
   AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
   if ((Boolean) proxyTargetClass) {
     AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
     return;
   }
 }
      }
    }
    if (!candidateFound && logger.isInfoEnabled()) {
      String name = getClass().getSimpleName();
      logger.info(String.format("%s was imported but no annotations were found " +
   "having both 'mode' and 'proxyTargetClass' attributes of type " +
   "AdviceMode and boolean respectively. This means that auto proxy " +
   "creator registration and configuration may not have occurred as " +
   "intended, and components may not be proxied as expected. Check to " +
   "ensure that %s has been @import'ed on the same class where these " +
   "annotations are declared; otherwise remove the import of %s " +
   "altogether.", name, name, name));
    }
  }

InfrastructureAdvisorAutoProxyCreator类的作用与AnnotationAwareAspectJAutoProxyCreator类的作用类似。

@SuppressWarnings("serial")
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
    implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {

4、ProxyTransactionManagementConfiguration类

代理事务管理配置类

@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());
    if (this.enableTx != null) {
      advisor.setOrder(this.enableTx.getNumber("order"));
    }
    return advisor;
  }
 
  @Bean
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public TransactionAttributeSource transactionAttributeSource() {
    return new AnnotationTransactionAttributeSource();
  }
 
  @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;
  }
 
}

TransactionInterceptor类,事务调用:invokeWithinTransaction()方法为最终执行的方法

@Override
  @Nullable
  public Object invoke(MethodInvocation invocation) throws Throwable {
    // Work out the target class: may be {@code null}.
    // The TransactionAttributeSource should be passed the target class
    // as well as the method, which may be from an interface.
    Class targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
 
    // Adapt to TransactionAspectSupport's invokeWithinTransaction...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
  }

TransactionAspectSupport类的最终事务方法执行:

@Nullable
  protected Object invokeWithinTransaction(Method method, @Nullable Class targetClass,
      final InvocationCallback invocation) throws Throwable {
 
    // If the transaction attribute is null, the method is non-transactional.
    TransactionAttributeSource tas = getTransactionAttributeSource();
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
 
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      // Standard transaction demarcation with getTransaction and commit/rollback calls.
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
 
      Object retVal;
      try {
 // This is an around advice: Invoke the next interceptor in the chain.
 // This will normally result in a target object being invoked.
 retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
 // target invocation exception
 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, 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;
      }
    }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持考高分网。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/134696.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号