spring5.x-declarative transaction principle and source code implementation

Above: spring5.x-AOP implementation principle and source code analysis

Articles in this series:
               

                    spring5.x-AOP implementation principle and source code analysis

                    spring5.x-listener principle and source code implementation

                    spring5.x-solve circular dependency analysis

                    spring5.x-IOC module source code learning

                    Spring5.x introduction and matching spring source code reading environment


Table of contents

Above: spring5.x-AOP implementation principle and source code analysis

Articles in this series:               

                    spring5.x-AOP implementation principle and source code analysis

                    spring5.x-listener principle and source code implementation

                    spring5.x-solve circular dependency analysis

                    spring5.x-IOC module source code learning

                    Spring5.x introduction and matching spring source code reading environment

basic knowledge

Implementation principle of spring transaction

Spring transactions work as follows:

spring transaction source code learning

@EnableTransactionManagement annotation

@EnableTransactionManagement->TransactionManagementConfigurationSelector类

@EnableTransactionManagement->TransactionManagementConfigurationSelector->PROXY

@EnableTransactionManagement->TransactionManagementConfigurationSelector->ASPECTJ

How are annotations used?

@Transactional

Agent implementation

at last


basic knowledge

Please study the original article first: spring transaction management

Implementation principle of spring transaction

The Spring framework provides support for transactions, allowing developers to easily manage transaction boundaries, control transaction propagation behavior, and transaction isolation levels in applications. The principles of Spring transactions are mainly based on two key concepts: transaction managers and aspects.

  1. Transaction Manager: The transaction manager is responsible for coordinating and managing the execution of transactions. It provides operations such as starting a transaction, committing a transaction, and rolling back a transaction. The Spring framework supports a variety of transaction managers, such as JDBC transaction manager, Hibernate transaction manager and JTA transaction manager. Developers can choose the appropriate transaction manager based on specific needs.

  2. Aspect: In the Spring framework, transaction management is implemented through AOP (Aspect-Oriented Programming). Through AOP, Spring can add transaction processing logic before and after method calls to control transactions. Developers can use declarative transaction management to configure transaction rules and apply them to target methods.

Spring transactions work as follows:

  1. Configure transaction manager: First, developers need to configure a suitable transaction manager in the Spring configuration file. You can choose to use the default transaction manager provided by the Spring framework, or you can customize a transaction manager.

  2. Define transaction rules: Developers can use Spring's declarative transaction management to define transaction rules. By using transaction aspects and pointcuts in the configuration file, you can specify which methods require transaction management, and set properties such as transaction propagation behavior and isolation level.

  3. Open transaction boundaries: When a method managed by the transaction manager is called, Spring will decide whether to open a transaction based on transaction rules. If a transaction needs to be started, the transaction manager creates a new transaction and associates it with the current thread.

  4. Transaction commit or rollback: After the method execution is completed, the transaction manager will decide whether to commit the transaction or rollback the transaction based on the execution result of the method. If the method execution is successful, the transaction manager will commit the transaction to make it effective; if the method execution fails, the transaction manager will roll back the transaction to make it invalid.

  5. Transaction propagation behavior: When calling another method managed by a transaction manager within a method, the transaction manager will determine whether to join an existing transaction or start a new transaction based on the transaction propagation behavior rules.

Summary: The principle of Spring transactions is based on the implementation of transaction managers and AOP. The transaction manager is responsible for the coordination and management of transactions, while AOP is responsible for adding transaction processing logic before and after method calls. By properly configuring transaction management and defining transaction rules, developers can easily manage transactions in Spring applications.

spring transaction source code learning

@EnableTransactionManagement annotation

c3de05056c545b04abd667d7960501d6.png

This annotation is used to start a transaction. Note that when using this annotation, a PlatformTransactionManager bean must be registered, otherwise an error will be reported.

@Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
@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 2147483647;
}

@EnableTransactionManagement->TransactionManagementConfigurationSelector类

Import via import: TransactionManagementConfigurationSelector

Note that the following import has proxy (PROXY) and aspect (ASPECTJ)

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
    public TransactionManagementConfigurationSelector() {
    }

    protected String[] selectImports(AdviceMode adviceMode) {
        switch(adviceMode) {
        //代理
        case PROXY:
        //这里有自动注册代理和
            return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
        //切面
        case ASPECTJ:
            return new String[]{"org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration"};
        default:
            return null;
        }
    }
}
@EnableTransactionManagement->TransactionManagementConfigurationSelector->PROXY

Code location: org.springframework.context.annotation.AutoProxyRegistrar

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.context.annotation;

import java.util.Iterator;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.config.AopConfigUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
//实现了ImportBeanDefinitionRegistrar接口。该类用于注册自动代理创建器。
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    private final Log logger = LogFactory.getLog(this.getClass());

    public AutoProxyRegistrar() {
    }
  //该方法根据传入的注解元数据和Bean定义注册表,查找具有特定属性的注解,并根据其属性值进行相应的操作。
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean candidateFound = false;
    //获取所有注解类型
        Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
    //获取迭代器
        Iterator var5 = annoTypes.iterator();
    //循环获取
        while(var5.hasNext()) {
      //获取下一个annotYPE
            String annoType = (String)var5.next();
      //获取属性
            AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
      //如果不为空才继续
            if (candidate != null) {
        //获取model属性
                Object mode = candidate.get("mode");
        //获取proxyTargetClass代理类的属性
                Object proxyTargetClass = candidate.get("proxyTargetClass");
        //两个都不为空 且类开为AdviceMode 且 proxyTargetClass
                if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
          //标记找到了修选的注解
                    candidateFound = true;
          //判断是AdviceMode类型注解
                    if (mode == AdviceMode.PROXY) {
            //通过aop方式注入到bean中(这里如果多次以第一次为主)
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
            //如果开启了cglib那么这里会进行代理开启(如果出现多次会进行覆盖)
                        if ((Boolean)proxyTargetClass) {
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
                }
            }
        }
    //若没有找到任务记录 进行提醒日志打印
        if (!candidateFound && this.logger.isWarnEnabled()) {
            String name = this.getClass().getSimpleName();
            this.logger.warn(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));
        }

    }
}

Derived from the above code: AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

Note the following: If there are multiple bean names with the same name when injected by spring, only one will be retained.

Code location: org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired

@Nullable
    private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
        Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
        if (registry.containsBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator")) {
      //如果包含了,那么会直接覆盖(aop的优先级更大)
      //所以如果你的事务注解@EnableTransactionManagement和@EnableAspectJAutoProxy不管你哪个配在上面,都会被@EnableAspectJAutoProxy覆盖掉。切记切记
            BeanDefinition apcDefinition = registry.getBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator");
            if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
                int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
                int requiredPriority = findPriorityForClass(cls);
                if (currentPriority < requiredPriority) {
                    apcDefinition.setBeanClassName(cls.getName());
                }
            }

            return null;
        } else {
            RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
            beanDefinition.setSource(source);
            beanDefinition.getPropertyValues().add("order", -2147483648);
            beanDefinition.setRole(2);
            registry.registerBeanDefinition("org.springframework.aop.config.internalAutoProxyCreator", beanDefinition);
            return beanDefinition;
        }
    }

Code location: org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration

The following class is a configuration class

//被注解为@Configuration。该类用于配置代理模式下的事务管理。
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
  //该Bean对象是BeanFactoryTransactionAttributeSourceAdvisor类型,用于提供事务增强器(TransactionAttributeSource和TransactionInterceptor)。
  @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;
  }
  //注册到Spring容器中。该Bean对象是AnnotationTransactionAttributeSource类型,用于从注解中获取事务属性。
  @Bean
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public TransactionAttributeSource transactionAttributeSource() {
    return new AnnotationTransactionAttributeSource();
  }
  //注册到Spring容器中。该Bean对象是TransactionInterceptor类型,用于实现具体的事务拦截逻辑。
  @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;
  }

}

父类:org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration

//为一个抽象类,被注解为@Configuration。该类用于提供抽象的事务管理配置,并实现了ImportAware接口。
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
  //enableTx是一个AnnotationAttributes类型的变量,表示通过@EnableTransactionManagement注解获取的启用事务管理的属性。
  protected AnnotationAttributes enableTx;

  //txManager是一个PlatformTransactionManager类型的变量,表示默认的事务管理器,可以通过TransactionManagementConfigurer进行配置。
  protected PlatformTransactionManager txManager;

//根据传入的注解元数据(importMetadata),通过AnnotationMetadata的getAnnotationAttributes方法获取EnableTransactionManagement注解的属性值,并将其转换为AnnotationAttributes对象赋值给enableTx变量。如果enableTx为空,则抛出IllegalArgumentException异常。
  @Override
  public void setImportMetadata(AnnotationMetadata importMetadata) {
    this.enableTx = AnnotationAttributes.fromMap(
        importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
    if (this.enableTx == null) {
      throw new IllegalArgumentException(
          "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
    }
  }
//通过该方法将configurers集合中的唯一一个TransactionManagementConfigurer对象的annotationDrivenTransactionManager方法返回的事务管理器赋值给txManager变量。(默认的事务管理器通过这个可以实现)
  @Autowired(required = false)
  void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
    if (CollectionUtils.isEmpty(configurers)) {
      return;
    }
    //仅允许配置一个
    if (configurers.size() > 1) {
      throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
    }
    TransactionManagementConfigurer configurer = configurers.iterator().next();
    this.txManager = configurer.annotationDrivenTransactionManager();
  }

  //注册到Spring容器中。该Bean对象是TransactionalEventListenerFactory类型,用于处理事务相关的事件监听。
  @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
  public TransactionalEventListenerFactory transactionalEventListenerFactory() {
    return new TransactionalEventListenerFactory();
  }

}

Code location: org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor

Back to this in the subclass just now: BeanFactoryTransactionAttributeSourceAdvisor

//继承自AbstractBeanFactoryPointcutAdvisor注意:这里的advisor跟我之前aop是不是很像,其实就是那个advisor。该类用于根据事务属性源(TransactionAttributeSource)创建切点(Pointcut)
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
  //是一个TransactionAttributeSource类型的变量,用于存储事务属性源。
  private TransactionAttributeSource transactionAttributeSource;
  //是一个TransactionAttributeSourcePointcut类型的成员变量,通过匿名内部类的方式创建,并重写了getTransactionAttributeSource方法,该方法返回transactionAttributeSource对象。
  private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
    @Override
    protected TransactionAttributeSource getTransactionAttributeSource() {
      return transactionAttributeSource;
    }
  };


  //用于设置transactionAttributeSource变量的值。(可以通过这个手动设置事务属性源)
  public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
    this.transactionAttributeSource = transactionAttributeSource;
  }

  //用于设置pointcut的类过滤器(ClassFilter)。默认情况下,使用ClassFilter.TRUE。
  public void setClassFilter(ClassFilter classFilter) {
    this.pointcut.setClassFilter(classFilter);
  }

  @Override
  public Pointcut getPointcut() {
    return this.pointcut;
  }

}

Okay, let’s pay attention to this next: AbstractBeanFactoryPointcutAdvisor

Code location: org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor

//重点只看这段 用于设置通知(Advice)。这个就是我们原来aop的设置,可以看下原来的aop
public void setAdvice(Advice advice) {
        synchronized(this.adviceMonitor) {
            this.advice = advice;
        }
    }

BeanFactoryTransactionAttributeSourceAdvisor->TransactionAttributeSourcePointcut

Return this: TransactionAttributeSourcePointcut

Code location: org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut

This class is the implementation of aspects applied to transactions. focus, focus, focus

//是一个抽象类,继承自StaticMethodMatcherPointcut类并实现了Serializable接口。
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
  //matches方法用于判断给定的方法和目标类是否匹配该切点。如果目标类不为null且是TransactionalProxy的子类或实现类,则返回false;否则,获取事务属性源(TransactionAttributeSource)并判断其是否为null,以及通过事务属性源获取给定方法和目标类的事务属性是否为null。如果事务属性为null,则返回false,否则返回true。(属于静态匹配)
  @Override
  public boolean matches(Method method, Class<?> targetClass) {
    if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
      return false;
    }
    TransactionAttributeSource tas = getTransactionAttributeSource();
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
  }

  @Override
  public boolean equals(Object other) {
    if (this == other) {
      return true;
    }
    if (!(other instanceof TransactionAttributeSourcePointcut)) {
      return false;
    }
    TransactionAttributeSourcePointcut otherPc = (TransactionAttributeSourcePointcut) other;
    return ObjectUtils.nullSafeEquals(getTransactionAttributeSource(), otherPc.getTransactionAttributeSource());
  }

  @Override
  public int hashCode() {
    return TransactionAttributeSourcePointcut.class.hashCode();
  }

  @Override
  public String toString() {
    return getClass().getName() + ": " + getTransactionAttributeSource();
  }


  //用于基于事务属性源来进行方法匹配和拦截。子类可以实现getTransactionAttributeSource方法来提供具体的事务属性源,从而根据事务的需求来进行方法的拦截和处理。
  protected abstract TransactionAttributeSource getTransactionAttributeSource();

}
@EnableTransactionManagement->TransactionManagementConfigurationSelector->ASPECTJ

The following one is relatively simple. It returns a string array containing TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME. Used when configuring transaction management and brokering. Transaction management refers to the management of database transactions, while proxy refers to adding additional logic processing before and after method calls.

case ASPECTJ:
        return new String[] {
            TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};

public static final String TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME =
      "org.springframework.transaction.aspectj.AspectJTransactionManagementConfiguration";

How are annotations used?

We all know that we use the @Transactional annotation to start transactions in the spring system.

I talked about advisor above. In fact, spring transactions also use the idea of ​​​​aop to implement the logic of aspects. It just has its own unique logic.

Code location: org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans

public List<Advisor> findAdvisorBeans() {
    //检查是否存在缓存的advisor bean名称数组cachedAdvisorBeanNames。如果cachedAdvisorBeanNames为空,那么调用BeanFactoryUtils工具类的beanNamesForTypeIncludingAncestors方法获取Advisor类型的bean名称,并将结果赋值给advisorNames,并将结果缓存到cachedAdvisorBeanNames中。
    String[] advisorNames = this.cachedAdvisorBeanNames; 
    if (advisorNames == null) {
        advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
        this.cachedAdvisorBeanNames = advisorNames;
    }
  //值为空则直返回一个空数组
    if (advisorNames.length == 0) {
        return new ArrayList();
    } else {
        List<Advisor> advisors = new ArrayList();
        String[] var3 = advisorNames;
        int var4 = advisorNames.length;
      //通过循环判断每个name是否符合条件
        for(int var5 = 0; var5 < var4; ++var5) {
            String name = var3[var5];
            if (this.isEligibleBean(name)) {
                //如果当前bean正在创建中(isCurrentlyInCreation),则跳过该advisor,并记录调试日志。
                if (this.beanFactory.isCurrentlyInCreation(name)) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("Skipping currently created advisor '" + name + "'");
                    }
                } else {
                    //加入到列表中
                    try {
                        advisors.add(this.beanFactory.getBean(name, Advisor.class));
                    } catch (BeanCreationException var10) {
                        Throwable rootCause = var10.getMostSpecificCause();
                        if (rootCause instanceof BeanCurrentlyInCreationException) {
                            BeanCreationException bce = (BeanCreationException)rootCause;
                            if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
                                if (logger.isDebugEnabled()) {
                                    logger.debug("Skipping advisor '" + name + "' with dependency on currently created bean: " + var10.getMessage());
                                }
                                continue;
                            }
                        }

                        throw var10;
                    }
                }
            }
        }

        return advisors;
    }
}
@Transactional

Enable transactions through this annotation. Then in the previous TransactionAttributeSourcePointcut.matches, we will identify whether the @Transactional annotation is included. If it is, it means that transactions are enabled.

The previous initialization logic is similar to aop. You can check aop. I won’t go into details here.

Code location: org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>)

//用于判断给定的类是否适用于指定的切点(Pointcut)。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
        //如果为空直接抛出异常
        Assert.notNull(pc, "Pointcut must not be null");
        //不是这类过滤直接返回
        if (!pc.getClassFilter().matches(targetClass)) {
            return false;
        } else {
            //如果 MethodMatcher 是 MethodMatcher.TRUE,表示匹配任何方法,则直接返回 true。
            MethodMatcher methodMatcher = pc.getMethodMatcher();
            if (methodMatcher == MethodMatcher.TRUE) {
                return true;
            } else {
                //如果 MethodMatcher 是 IntroductionAwareMethodMatcher 的实例,将其赋值给 introductionAwareMethodMatcher。
                IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
                //判断是否这种类型
                if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
                    introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher)methodMatcher;
                }
              //用于保存目标class的对象
                Set<Class<?>> classes = new LinkedHashSet(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
                classes.add(targetClass);
                Iterator var6 = classes.iterator();
              //循环所有类对象
                while(var6.hasNext()) {
                    Class<?> clazz = (Class)var6.next();
                    //获取所有方法
                    Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
                    Method[] var9 = methods;
                    int var10 = methods.length;
                  //通过matches来匹配方法(就是前面那个方法)
                    for(int var11 = 0; var11 < var10; ++var11) {
                        Method method = var9[var11];
                        if (introductionAwareMethodMatcher != null && introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) || methodMatcher.matches(method, targetClass)) {
                            return true;
                        }
                    }
                }

                return false;
            }
        }
    }

Note here: TransactionAttributeSourcePointcut.matches

This method was implemented just before initialization. This is used to determine whether it is a transaction or pure aop.

@Override
  public boolean matches(Method method, Class<?> targetClass) {
    if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
      return false;
    }
    TransactionAttributeSource tas = getTransactionAttributeSource();
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
  }

接下来:org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute

//重写了某个接口或者父类的getTransactionAttribute方法。
@Override
  public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
        //如果是object类型 直接返回
    if (method.getDeclaringClass() == Object.class) {
      return null;
    }

    // 生成一个缓存键(cacheKey),用于在属性缓存中查找或存储事务属性。
    Object cacheKey = getCacheKey(method, targetClass);
        //获取缓存中的值
    TransactionAttribute cached = this.attributeCache.get(cacheKey);
        //有值
    if (cached != null) {
      //判断是否为为空事务属性的对象,是直接返回null
      if (cached == NULL_TRANSACTION_ATTRIBUTE) {
        return null;
      }
      else {
                //不是返回该值
        return cached;
      }
    }
    else {
      // 如果缓存没有,那么查下事务注解中的属性
      TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
      // 解析出来为空 直放入缓存
      if (txAttr == null) {
        this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
      }
      else {
                //通过全类名+方法名生成方法标识
        String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
                //如果为DefaultTransactionAttribute 类型 则添加到属性中
        if (txAttr instanceof DefaultTransactionAttribute) {
          ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
        }
                //判断日志开关,有则打印日志
        if (logger.isDebugEnabled()) {
          logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
        }
                //最后加到缓存中
        this.attributeCache.put(cacheKey, txAttr);
      }
            //返回
      return txAttr;
    }
  }

Pay attention to the following: TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);

The implementation is as follows:

protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
    //判断是不是public 修饰的方法(这里也就是我们常说事务必须是public),发果不是直接返回null
    if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
    }

    // 获取目标类的用户类(userClass),忽略可能存在的 CGLIB 子类,仅对实际的用户类进行分析。
    Class<?> userClass = ClassUtils.getUserClass(targetClass);
    // The method may be on an interface, but we need attributes from the target class.
    // 获取最具体的方法(specificMethod),即在目标类及其父类/接口中查找最匹配的方法。
    Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
    //如果处理的方法包含泛型参数,则找到原始方法(BridgeMethodResolver.findBridgedMethod(specificMethod))。
    specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

    // 获取目前类是否有事务的属性,有则直接返回
    TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
    if (txAttr != null) {
      return txAttr;
    }

    // 如果目标类的方法中没有找到事务属性,则尝试从目标类本身获取事务属性(findTransactionAttribute(specificMethod.getDeclaringClass()))。
    txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
        //找到了事务属性,并且当前处理的是用户级别的方法(ClassUtils.isUserLevelMethod(method) 返回 true),则返回该事务属性
    if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
      return txAttr;
    }
      //如果是接口方法
    if (specificMethod != method) {
      // 去接口上方法找事务注解,如果不为空则直接返回
      txAttr = findTransactionAttribute(method);
      if (txAttr != null) {
        return txAttr;
      }
      // 去实现类找,如果不为空,有则返回
      txAttr = findTransactionAttribute(method.getDeclaringClass());
      if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
        return txAttr;
      }
    }
      //最后啥都没就返回空
    return null;
  }

The above logic is -> judge it as public -> go to the target transaction annotation to find it -> go to the interface to find it -> go to the interface implementation class to find it

Agent implementation

Then you need to understand how transactions are implemented by proxy. In fact, the first section of the spring call is the same as aop. It is just that during the call, you need to determine which kind of agent, aop or cglib or the introduced framework.

Jump off the logic here, because the previous aop type goes directly to this class: TransactionAspectSupport

Code location: org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

//代理调用模版
  protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
      throws Throwable {

    // If the transaction attribute is null, the method is non-transactional.
        //获取事务属性
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
        //获取配置 的事务管理器对象
    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;
      }
    }
  }

In fact, the above logic is to create a transaction->execute the transaction->rollback/complete the transaction

Take a look at this method inside: TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

protected TransactionInfo createTransactionIfNecessary(
      PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {

    // 不为空 则名称为空 
    if (txAttr != null && txAttr.getName() == null) {
            //通过连接点的ID定义成事务的名称
      txAttr = new DelegatingTransactionAttribute(txAttr) {
        @Override
        public String getName() {
          return joinpointIdentification;
        }
      };
    }

    TransactionStatus status = null;
    if (txAttr != null) {
      if (tm != null) {
                //获取事务状态
        status = tm.getTransaction(txAttr);
      }
      else {
        if (logger.isDebugEnabled()) {
          logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
              "] because no transaction manager has been configured");
        }
      }
    }
        //将事务的信息封装到 TransactionInfo 并返回
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
  }

In the code: status = tm.getTransaction(txAttr);

Code location: org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

@Override
  public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
        //获取当前的事务对象。
    Object transaction = doGetTransaction();

    
    boolean debugEnabled = logger.isDebugEnabled();
      //判断方法传递为空
    if (definition == null) {
      //使用默认的进行实始化
      definition = new DefaultTransactionDefinition();
    }
      //该事务已存在
    if (isExistingTransaction(transaction)) {
      // Existing transaction found -> check propagation behavior to find out how to behave.
            //处理存在的事务并返回
      return handleExistingTransaction(definition, transaction, debugEnabled);
    }

    //检事事务设置的超时时间,如果超时则抛出悍异常
    if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
      throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
    }

    // 如果为事务为运行中的事务中,则抛出异常(代表没有事务)
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
      throw new IllegalTransactionStateException(
          "No existing transaction found for transaction marked with propagation 'mandatory'");
    }
            /*
            如果不存在已有的事务,则根据传入的事务定义的传播行为来决定如何处理新的事务。
如果传播行为为 PROPAGATION_MANDATORY,则抛出 IllegalTransactionStateException 异常,表示标记为 "mandatory" 的事务没有找到现有的事务。
如果传播行为为 PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW 或 PROPAGATION_NESTED,则挂起当前事务资源,并创建一个新的事务,并返回一个新的 DefaultTransactionStatus 对象作为事务状态。在创建新事务之前,会检查是否需要同步事务,并准备相应的事务同步。如果在创建新事务过程中发生异常,则恢复挂起的事务资源,并重新抛出异常。
如果传播行为为其他值,则说明不需要实际的事务,但可能需要进行事务同步,所以会返回一个空的事务状态对象。
这里相当啰嗦~
            */
    else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
        definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
        definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      SuspendedResourcesHolder suspendedResources = suspend(null);
      if (debugEnabled) {
        logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
      }
      try {
                //同步状态
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
                //构建事务的状态
        DefaultTransactionStatus status = newTransactionStatus(
            definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
                //创建一个新事务
        doBegin(transaction, definition);
                //绑定到线程变量去(这里相当复杂)
        prepareSynchronization(status, definition);
                //返回状态
        return status;
      }
      catch (RuntimeException ex) {
        resume(null, suspendedResources);
        throw ex;
      }
      catch (Error err) {
        resume(null, suspendedResources);
        throw err;
      }
    }
    else {
            //下面是创建一个空事务
      // Create "empty" transaction: no actual transaction, but potentially synchronization.
      if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
        logger.warn("Custom isolation level specified but no actual transaction initiated; " +
            "isolation level will effectively be ignored: " + definition);
      }
      boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
      return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
    }
  }

6b28ad6e22f1c752911cdfbf3dbb6da6.png

df0dbcd6fc632880cffe4113edc73c6c.png

Regarding the communication behavior of transactions, please read it yourself or read the article: spring transaction management

Next code: doBegin(transaction, definition);

There are three implementations. The second one is used here.

000a7154a15a6663bf66c17c07fbf1e0.png

org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

//
protected void doBegin(Object transaction, TransactionDefinition definition) {
    //转为事务对象 
    DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
    
        Connection con = null;

        try {
            //通过数据源获取数据库连接
            if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                //获取边接
                Connection newCon = this.dataSource.getConnection();
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                }
              //将数据库连接包装成一个ConnectionHolder,并放到 txObject属性中
                txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
            }
          //标记当前连接为同步事务
            txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
            //获取连接
            con = txObject.getConnectionHolder().getConnection();
            //获取事务隔离级别,根据事务定义对连接进行必要的准备工作
            Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
            //设置进属性
            txObject.setPreviousIsolationLevel(previousIsolationLevel);
            //自动提交默认为true
            if (con.getAutoCommit()) {
                txObject.setMustRestoreAutoCommit(true);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                }
              //开启事务
                con.setAutoCommit(false);
            }
          //判断事务是否只读
            this.prepareTransactionalConnection(con, definition);
            //设置事务为激活状态
            txObject.getConnectionHolder().setTransactionActive(true);
            //获取超时时间
            int timeout = this.determineTimeout(definition);
            //不为-1则进行设置超时时间属性
            if (timeout != -1) {
                txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
            }
          //如果为一个新事我国
            if (txObject.isNewConnectionHolder()) {
                //绑定key 和value 到线程池中
                TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder());
            }

        } catch (Throwable var7) {
            //如果在上述过程中发生异常,则会释放连接并抛出 CannotCreateTransactionException 异常,表示无法为事务打开数据库连接。
            if (txObject.isNewConnectionHolder()) {
                DataSourceUtils.releaseConnection(con, this.dataSource);
                txObject.setConnectionHolder((ConnectionHolder)null, false);
            }

            throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7);
        }
    }

The above logic is relatively easy to understand. After all, as long as you finish learning jdbc, you can basically understand it.

Finally, there is another kind of transaction which is a nested transaction, so let’s learn about this one too.

Go back to this position: org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

if (isExistingTransaction(transaction)) {
      // Existing transaction found -> check propagation behavior to find out how to behave.
      return handleExistingTransaction(definition, transaction, debugEnabled);
    }
private TransactionStatus handleExistingTransaction(
      TransactionDefinition definition, Object transaction, boolean debugEnabled)
      throws TransactionException {
      //存在事务则跑出异常
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
      throw new IllegalTransactionStateException(
          "Existing transaction found for transaction marked with propagation 'never'");
    }
      //存在外部事务则挂起事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
      if (debugEnabled) {
        logger.debug("Suspending current transaction");
      }
            //挂起事务
      Object suspendedResources = suspend(transaction);
      boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
            //创建一个新的非事务状态并返回
      return prepareTransactionStatus(
          definition, null, false, newSynchronization, debugEnabled, suspendedResources);
    }
      //存在外部事务,挂起外部事务,新建一个事务
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
      if (debugEnabled) {
        logger.debug("Suspending current transaction, creating new transaction with name [" +
            definition.getName() + "]");
      }
      SuspendedResourcesHolder suspendedResources = suspend(transaction);
      try {
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        DefaultTransactionStatus status = newTransactionStatus(
            definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
        doBegin(transaction, definition);
        prepareSynchronization(status, definition);
        return status;
      }
      catch (RuntimeException beginEx) {
        resumeAfterBeginException(transaction, suspendedResources, beginEx);
        throw beginEx;
      }
      catch (Error beginErr) {
        resumeAfterBeginException(transaction, suspendedResources, beginErr);
        throw beginErr;
      }
    }
      //存在外部事务,融进外部事务中
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      if (!isNestedTransactionAllowed()) {
        throw new NestedTransactionNotSupportedException(
            "Transaction manager does not allow nested transactions by default - " +
            "specify 'nestedTransactionAllowed' property with value 'true'");
      }
      if (debugEnabled) {
        logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
      }
            //支持保存在
      if (useSavepointForNestedTransaction()) {
      
                //开启一个新的事务并返回状态
        DefaultTransactionStatus status =
            prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
                //为事务创建一个回滚的点
        status.createAndHoldSavepoint();
        return status;
      }
      else {
        // Nested transaction through nested begin and commit/rollback calls.
        // Usually only for JTA: Spring synchronization might get activated here
        // in case of a pre-existing JTA transaction.
        boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
        DefaultTransactionStatus status = newTransactionStatus(
            definition, transaction, true, newSynchronization, debugEnabled, null);
        doBegin(transaction, definition);
        prepareSynchronization(status, definition);
        return status;
      }
    }

    // Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
    if (debugEnabled) {
      logger.debug("Participating in existing transaction");
    }
        //是否验证事务
    if (isValidateExistingTransaction()) {
      if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
                //当前事务等级
        Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
                //为空或等级不一致 则抛出异常
        if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
                    
          Constants isoConstants = DefaultTransactionDefinition.constants;
          throw new IllegalTransactionStateException("Participating transaction with definition [" +
              definition + "] specifies isolation level which is incompatible with existing transaction: " +
              (currentIsolationLevel != null ?
                  isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
                  "(unknown)"));
        }
      }
            //不是为只读 且不一致 则抛出异常
      if (!definition.isReadOnly()) {
        if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
          throw new IllegalTransactionStateException("Participating transaction with definition [" +
              definition + "] is not marked as read-only but existing transaction is");
        }
      }
    }
    //最后 创建一个新的同步 并返回状态
    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
  }

These operations will eventually be executed by doComit()

8b19915fe25d782e085bbb67cb94b2ac.png

Rollback if failed.

at last

The core idea of ​​Spring transaction management is to separate transaction control from business logic, so that business code does not need to pay attention to details such as transaction opening, submission or rollback. By using Spring's transaction manager and declarative transaction configuration, transaction logic can be decoupled from business code, providing a more flexible and simpler transaction management method. Relatively speaking, spring transactions are more complex than aop and require a foundation of aop+jdbc. This article is relatively one-sided and may not be easy to understand. If you really can’t understand it, I suggest you refer to the following article for comparison.

Reference article:

https://juejin.cn/post/6887751198737170446

https://blog.csdn.net/rongtaoup/article/details/127688984

https://www.cnblogs.com/dennyzhangdd/p/9602673.html

Guess you like

Origin blog.csdn.net/qq_16498553/article/details/132530610