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

Spring事务原理

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

Spring事务原理

Spring事务

Spring事务通过AOP切面来增强目标方法的调用,控制事务的开启、提交和回滚。主要的接口有:

  • TransactionManager:Spring事务管理器实现的标志接口,对标准事务和反应式事务都可用;
  • TransactionStatus:代表事务的状态,事务代码可以使用它来获取事务的状态,也可以在失败的时候,编码式的请求一个回滚;他还包含了SavepointManager接口,用来访问保存点管理信息;注意只有底层事务管理器支持的时候,才能使用保存点管理器。
  • TransactionDefinition:定义符合 Spring 的事务属性的接口,基于类似于 EJB CMT 属性的传播行为定义。
  • SavepointManager:定义一个API,以一种通用的方式来编程式管理事务保存点的接口

Spring事务分为两种:编程式事务和声明式事务

  • 编程式事务:通过编写事务相关的代码来实现对事务开启、提交和回滚的手动控制
  • 声明式事务:一般是通过在方法或者类上面加@Transactional注解来实现
关键注解

声明式事务主要通过**@EnableTransactionManagement注解声明使用事务,加载配置项;使用@Transactional**注解声明方法或类按事务方式运行

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

    // 是否创建基于CGLIB的子类代理,默认使用标准JAVA的基于接口的JDK代理
   boolean proxyTargetClass() default false;

    // 事务的advice应该怎么样应用,默认是代理模式
   AdviceMode mode() default AdviceMode.PROXY;

    // 当多个advice在特定的加入点被使用的时候,他可以定义事务advisor的执行顺序
   int order() default Ordered.LOWEST_PRECEDENCE;

}
TransactionManagementConfigurationSelector

该注解上使用@Import导入了TransactionManagementConfigurationSelector相关的配置,TransactionManagementConfigurationSelector类会根据不同的模式(代理模式,切面模式)来加载不同的配置

// 基于导入的配置类中的值选择AbstractTransactionManagementConfiguration的实现
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {

   // 根据EnableTransactionManagement注解中配置的模式返回配置类
   @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);
   }

}

代理模式中的AutoProxyRegistrar和ProxyTransactionManagementConfiguration可以创建自动代理、生成BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource和TransactionInterceptor等事务必要的属性源和拦截器;

AutoProxyRegistrar

AutoProxyRegistrar主要是解析@EnableTransactionManagement注解的属性,根据模式等注册自动代理

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
   private final Log logger = LogFactory.getLog(getClass());
    
   @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));
      }
   }

}

AopConfigUtils#registerAutoProxyCreatorIfNecessary会注册org.springframework.aop.config.internalAutoProxyCreator的bean信息

public abstract class AopConfigUtils {
	public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
    
    private static BeanDefinition registerOrEscalateApcAsRequired( Class cls, BeanDefinitionRegistry registry,
                                                                  @Nullable Object source) {

       Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

       if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
          BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
          if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
             int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
             int requiredPriority = findPriorityForClass(cls);
             if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
             }
          }
          return null;
       }

       RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
       beanDefinition.setSource(source);
       beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
       beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
       registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
       return beanDefinition;
    }
}
ProxyTransactionManagementConfiguration

ProxyTransactionManagementConfiguration是一个配置类,他会注册BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor这三个bean,下面来看看这三个bean的主要作用

@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

    // 由一个TransactionAttributeSource驱动的advisor, 用来为事务方法提供事务advice
   @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.getNumber("order"));
      }
      return advisor;
   }

    // 被事务拦截器使用,是元数据恢复的策略接口;事务属性相关信息可能来源于配置或元数据
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionAttributeSource transactionAttributeSource() {
      return new AnnotationTransactionAttributeSource();
   }

    // 事务拦截器
   @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;
   }

}

TransactionInterceptor事务拦截器的继承关系如下图:

MethodInterceptor#invoke方法采用CGLIB动态代理,生成目标方法的子类,可以对目标方法进行拦截,然后就在目标方法的执行前后进行一些特殊的处理

TransactionInterceptor继承了TransactionAspectSupport,并且实现了MethodInterceptor接口,可以拦截事务方法,将方法的逻辑放在事务中执行。

TransactionInterceptor#invoke方法先获取目标类,然后调用父类TransactionAspectSupport#invokeWithinTransaction方法,以事务的方式执行业务逻辑

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#invokeWithinTransaction方法,他会根据不同的事务类型分别执行对应的处理逻辑,可以支持反应式事务、普通事务和带回调的事务

protected Object invokeWithinTransaction(Method method, @Nullable Class targetClass,
      final InvocationCallback invocation) throws Throwable {

    // 如果事务属性为null,那这个方法是非事务的
   TransactionAttributeSource tas = getTransactionAttributeSource();
   final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    // 确定事务管理器TM
   final TransactionManager tm = determineTransactionManager(txAttr);

    // 反应式事务
   if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
       // 获取反应式事务支持
      ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
         if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
            throw new TransactionUsageException(
                  "Unsupported annotated transaction on suspending function detected: " + method +
                  ". Use TransactionalOperator.transactional extensions instead.");
         }
         ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
         if (adapter == null) {
            throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
                  method.getReturnType());
         }
         return new ReactiveTransactionSupport(adapter);
      });
       // 调用目标方法
      return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
   }

    // 转化为平台事务
   PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
    // 识别目标方法
   final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    
   // 标准事务处理
   if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
       // 创建标准事务
      TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
      Object retVal;
      try {
          // 这是一个环绕advice,会在调用链里调用下一个拦截器;他通常会导致目标方法被调用
          // 调用目标方法
         retVal = invocation.proceedWithInvocation();
      } catch (Throwable ex) {
         // target invocation exception
         completeTransactionAfterThrowing(txInfo, ex);
         throw ex;
      } finally {
          // 清除事务信息
         cleanupTransactionInfo(txInfo);
      }
      // 匹配到回滚规则时设置回滚
      if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
         // Set rollback-only in case of Vavr failure matching our rollback rules...
         TransactionStatus status = txInfo.getTransactionStatus();
         if (status != null && txAttr != null) {
            retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
         }
      }
      // 返回后提交事务
      commitTransactionAfterReturning(txInfo);
      return retVal;
       
   } else { // 带回调的事务
      final ThrowableHolder throwableHolder = new ThrowableHolder();

      // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
      try {
         Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
             // 准备事务信息
            TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
            try {
                // 调用目标方法
               Object retVal = invocation.proceedWithInvocation();
                // 匹配到回滚规则时设置回滚
               if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                  // Set rollback-only in case of Vavr failure matching our rollback rules...
                  retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
               }
               return retVal;
            } 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;
      }
   }
}
@Transactional

该注解可以标记方法或类,使其以事务的方式运行

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {

   
   @AliasFor("transactionManager")
   String value() default "";

   
   @AliasFor("value")
   String transactionManager() default "";

   
   Propagation propagation() default Propagation.REQUIRED;

   
   Isolation isolation() default Isolation.DEFAULT;

   
   int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;

   
   boolean readOnly() default false;

   
   Class[] rollbackFor() default {};

   
   String[] rollbackForClassName() default {};

   
   Class[] noRollbackFor() default {};

   
   String[] noRollbackForClassName() default {};

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

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

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