Spring事务

传播特性

REQUIRED

当前方法存在事务时,子方法加入该事务。此时父子方法共用一个事务,无论父子方法哪个发生异常回滚,整个事务都回滚。即使父方法捕捉了异常,也是会回滚。而当前方法不存在事务时,子方法新建一个事务。

REQUIRES_NEW

无论当前方法是否存在事务,子方法都新建一个事务。此时父子方法的事务时独立的,它们都不会相互影响。但父方法需要注意子方法抛出的异常,避免因子方法抛出异常,而导致父方法回滚

NESTED

当前方法存在事务时,子方法加入在嵌套事务执行。当父方法事务回滚时,子方法事务也跟着回滚。当子方法事务发送回滚时,父事务是否回滚取决于是否捕捉了异常。如果捕捉了异常,那么就不回滚,否则回滚。

SUPPORTS

如果当前上下文中存在事务,那么加入该事务;否则用非事务方式执行

MANDATORY

当前方法必须要在有事务方法中运行,不然就抛出异常;如果有事务,就加入当前事务

NOT_SUPPORTED

如果当前上下文中存在事务,则挂起事务,新方法在没有事务的环境中执行

NEVER

当前方法不应该运行在事物中,如果有事务就抛出异常

源码

解析<tx:annotation-driven/>标签

class AnnotationDrivenBeanDefinitionParser implements BeanDefinitionParser {
  /**
    * 解析 <tx:annotation-driven/> 标签
    */
  @Override
  @Nullable
  public BeanDefinition parse(Element element, ParserContext parserContext) {
    registerTransactionalEventListenerFactory(parserContext);
    String mode = element.getAttribute("mode");
    if ("aspectj".equals(mode)) {
      // mode="aspectj"
      registerTransactionAspect(element, parserContext);
      if (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader())) {
        registerJtaTransactionAspect(element, parserContext);
      }
    }
    else {
      // mode="proxy"
      AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext);
    }
    return null;
  }

  private static class AopAutoProxyConfigurer {

    public static void configureAutoProxyCreator(Element element, ParserContext parserContext) {
      // 注册 InfrastructureAdvisorAutoProxyCreator
      AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);

      String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME;
      if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) {
        Object eleSource = parserContext.extractSource(element);

        // 注册 AnnotationTransactionAttributeSource
        // 用来找 Transaction 注解
        RootBeanDefinition sourceDef = new RootBeanDefinition(
          "org.springframework.transaction.annotation.AnnotationTransactionAttributeSource");
        sourceDef.setSource(eleSource);
        sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef);

        // 注册 TransactionInterceptor
        // 事务拦截器,执行方法时,开启事务/回滚事务/提交事务
        RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class);
        interceptorDef.setSource(eleSource);
        interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        registerTransactionManager(element, interceptorDef);
        interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef);

        // 注册 BeanFactoryTransactionAttributeSourceAdvisor
        // BeanFactoryTransactionAttributeSourceAdvisor 又是一个 PointcutAdvisor ,有一个切入点 TransactionAttributeSourcePointcut
        // TransactionAttributeSourcePointcut 用来匹配方法
        RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class);
        advisorDef.setSource(eleSource);
        advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
        advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName));
        advisorDef.getPropertyValues().add("adviceBeanName", interceptorName);
        if (element.hasAttribute("order")) {
          advisorDef.getPropertyValues().add("order", element.getAttribute("order"));
        }
        parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef);

        CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
        compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName));
        compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName));
        compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));
        parserContext.registerComponent(compositeDef);
      }
    }
  }
}

InfrastructureAdvisorAutoProxyCreator的祖父类AbstractAutoProxyCreator,实现了postProcessAfterInitialization方法,在 Bean 初始化后,会调用postProcessAfterInitialization方法用来创建代理对象

public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
  implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
  public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
    if (bean != null) {
      // cacheKey就是beanName或者beanClass
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (this.earlyProxyReferences.remove(cacheKey) != bean) {
        // 需要的话就使用动态代理产生代理对象
        // bean : 目标对象
        // beanName :目标对象名称
        // cacheKey:就是beanName或者beanClass
        return wrapIfNecessary(bean, beanName, cacheKey);
      }
    }
    return bean;
  }

  protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
      return bean;
    }
    // 如果已经增强了,则不需要再生成代理了
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
      return bean;
    }
    // isInfrastructureClass方法:Advice/Pointcut/Advisor/AopInfrastructureBean接口的beanClass不代理
    // shouldSkip方法:对beanName为.ORIGINAL结尾的bean不做代理
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
      this.advisedBeans.put(cacheKey, Boolean.FALSE);
      return bean;
    }

    // 查找合适的Advisor(增强器)
    // 第一步:找到候选的Advisor,这里我们讲的是 Transactional,所以找到的是前面注册的 BeanFactoryTransactionAttributeSourceAdvisor
    // 第二步:找到合适的Advisor,BeanFactoryTransactionAttributeSourceAdvisor 又是一个 PointcutAdvisor ,有一个切入点 TransactionAttributeSourcePointcut ,通过 ClassFilter 和 MethodMatcher 来判断是否是合适 Advisor 。
    // 这里的 ClassFilter 是 ClassFilter.TRUE ,永远返回 TRUE 
    // 这里的 MethodMatcher 其实也是 TransactionAttributeSourcePointcut ,调用 matches 方法其实会调用之前注册的 AnnotationTransactionAttributeSource
    // 有兴趣的小伙伴可以跟一下源码
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

    // 对相应的advisor不为空才采取代理
    if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
      // 通过jdk动态代理或者cglib动态代,产理生代理对象
      // 第三步:针对目标对象产生代理对象
      Object proxy = createProxy(
        bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
      // 放入代理类型缓存
      this.proxyTypes.put(cacheKey, proxy.getClass());
      return proxy;
    }
    // 放入通知缓存
    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
  }

  protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
                               @Nullable Object[] specificInterceptors, TargetSource targetSource) {
    // 略。。。

    // 获取使用JDK动态代理或者cglib动态代理产生的对象
    return proxyFactory.getProxy(getProxyClassLoader());
  }
}
public class ProxyFactory extends ProxyCreatorSupport {
  public Object getProxy(@Nullable ClassLoader classLoader) {
    return createAopProxy().getProxy(classLoader);
  }
}

createAopProxy()返回有CglibAopProxyJdkDynamicAopProxy,分别是 Cglib 代理和 JDK 动态代理。我们这里看 JDK 动态代理。

final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
  public Object getProxy(@Nullable ClassLoader classLoader) {
    if (logger.isDebugEnabled()) {
      logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
    }
    // 获取完整的代理接口
    Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
    findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
    // 调用JDK动态代理方法
    return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
  }
}

JdkDynamicAopProxy也是一个InvocationHandler,当执行代理对象的方法时,就会执行JdkDynamicAopProxy#invoke方法。继续跟JdkDynamicAopProxy#invoke发现会拿到TransactionInterceptor,并执行invoke方法。我们主要看一下TransactionInterceptor#invoke方法

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {

  public Object invoke(MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // Adapt to TransactionAspectSupport's invokeWithinTransaction...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
  }
}

invokeWithinTransaction是父类的方法

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

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

    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)) {
      // 创建事务并返回事务对象信息
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

      Object retVal;
      try {
        // 执行下一个拦截器,最终会执行连接点的方法()
        retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
        // 事务回滚
        completeTransactionAfterThrowing(txInfo, ex);
        throw ex;
      }
      finally {
        // 清除事务信息
        cleanupTransactionInfo(txInfo);
      }
      // 提交事务
      commitTransactionAfterReturning(txInfo);
      return retVal;
    }
    else {
      // 略。。。
    }
  }
}

实现事务提交后的操作

如果想在事务提交之后干点什么事,我们跟一下commitTransactionAfterReturning方法,发现会调用AbstractPlatformTransactionManager#processCommit方法

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
  private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
      // 略。。。

      // Trigger afterCommit callbacks, with an exception thrown there
      // propagated to callers but the transaction still considered as committed.
      try {
        // 事务提交后,触发 TransactionSynchronization#afterCommit
        triggerAfterCommit(status);
      }
      finally {
        // 触发 TransactionSynchronization#afterCompletion
        triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
      }

    }
    finally {
      // 最终会清除掉所有的 TransactionSynchronization
      cleanupAfterCompletion(status);
    }
  }

  private void triggerAfterCommit(DefaultTransactionStatus status) {
    if (status.isNewSynchronization()) {
      if (status.isDebug()) {
        logger.trace("Triggering afterCommit synchronization");
      }
      TransactionSynchronizationUtils.triggerAfterCommit();
    }
  }
}

TransactionSynchronizationUtils.triggerAfterCommit()是事务提交后触发回调的入口

public abstract class TransactionSynchronizationUtils {
  public static void triggerAfterCommit() {
    invokeAfterCommit(TransactionSynchronizationManager.getSynchronizations());
  }

  public static void invokeAfterCommit(@Nullable List<TransactionSynchronization> synchronizations) {
    if (synchronizations != null) {
      for (TransactionSynchronization synchronization : synchronizations) {
        // 事务提交后触发的方法
        synchronization.afterCommit();
      }
    }
  }
}

synchronizations是一个ThreadLocal对象,所以是线程隔离的。并且最终会在cleanupAfterCompletion方法清除掉synchronizations,不用担心内存泄漏等后果

public abstract class TransactionSynchronizationManager {
  private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal<>("Transaction synchronizations");
}

上述代码可以看到,上述代码可以看到,遍历TransactionSynchronization集合,执行afterCommit方法。

如果想在事务提交后做些操作,那可以在TransactionSynchronizationManager注册一个TransactionSynchronization,在afterCommit方法实现事务提交之后我们自己的操作

TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
  @Override
  public void afterCommit() {
    // 事务提交后的逻辑
  }
});
posted @ 2022-11-06 17:48  咖啡因的取悦  阅读(74)  评论(0)    收藏  举报