前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring5.x-声明式事务原理及源码实现

spring5.x-声明式事务原理及源码实现

作者头像
逍遥壮士
发布2023-09-01 17:07:44
4760
发布2023-09-01 17:07:44
举报
文章被收录于专栏:技术趋势

基础知识

请先学习原来的文章:spring事务管理

spring事务的实现原理

Spring框架提供了对事务的支持,使得开发者能够在应用程序中轻松地管理事务的边界、控制事务的传播行为和事务的隔离级别。Spring事务的原理主要基于两个关键概念:事务管理器和切面。

  1. 事务管理器(Transaction Manager):事务管理器负责协调和管理事务的执行。它提供了开始事务、提交事务和回滚事务等操作。Spring框架支持多种事务管理器,如JDBC事务管理器、Hibernate事务管理器和JTA事务管理器等。开发者可以根据具体的需求选择合适的事务管理器。
  2. 切面(Aspect):在Spring框架中,事务管理通过AOP(面向切面编程)实现。通过AOP,Spring能够在方法调用前后添加事务处理逻辑,从而实现对事务的控制。开发者可以使用声明式事务管理来配置事务规则,并将其应用到目标方法上。

Spring事务的工作原理如下:

  1. 配置事务管理器:首先,开发者需要在Spring配置文件中配置一个合适的事务管理器。可以选择使用Spring框架提供的默认事务管理器,也可以自定义实现一个事务管理器。
  2. 定义事务规则:开发者可以使用Spring的声明式事务管理来定义事务规则。通过在配置文件中使用事务切面和切点的方式,可以指定哪些方法需要进行事务管理,并设置事务的传播行为和隔离级别等属性。
  3. 开启事务边界:当一个被事务管理器管理的方法被调用时,Spring会根据事务规则决定是否开启一个事务。如果需要开启事务,则事务管理器会创建一个新的事务,并将其与当前线程关联起来。
  4. 事务提交或回滚:方法执行完成后,事务管理器会根据方法的执行结果决定是提交事务还是回滚事务。如果方法执行成功,事务管理器会提交事务,使其生效;如果方法执行失败,事务管理器会回滚事务,使其失效。
  5. 事务的传播行为:在一个方法内部调用另一个被事务管理器管理的方法时,事务管理器会根据事务的传播行为规则来确定是否加入已有的事务或开启一个新的事务。

总结:Spring事务的原理是基于事务管理器和AOP的实现。事务管理器负责事务的协调和管理,而AOP则负责在方法调用前后添加事务处理逻辑。通过合理配置事务管理和定义事务规则,开发者可以很方便地在Spring应用程序中进行事务管理。

spring事务源码学习

@EnableTransactionManagement注解

这个注解用于启动事务,注意在使用该注解的时候必须要有一个PlatformTransactionManager的bean注册,否则会报错。

代码语言:javascript
复制
@Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
代码语言:javascript
复制
@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进行导入:TransactionManagementConfigurationSelector

注意下面这个导入呢有代理(PROXY)的和切面(ASPECTJ)

代码语言:javascript
复制
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

代码位置:org.springframework.context.annotation.AutoProxyRegistrar

代码语言:javascript
复制
//
// 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));
        }

    }
}

从上面的代码衍生:AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

注意下面:spring在注入的时候如果有多个bean名称是一样的,那么只会保留一个。

代码位l置:org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired

代码语言:javascript
复制
@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;
        }
    }

代码位置:org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration

下面这个类是一个配置类

代码语言:javascript
复制
//被注解为@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

代码语言:javascript
复制
//为一个抽象类,被注解为@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();
  }

}

代码位置:org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor

回到刚才子类中的这个:BeanFactoryTransactionAttributeSourceAdvisor

代码语言:javascript
复制
//继承自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;
  }

}

好下接下来注意一下这个:AbstractBeanFactoryPointcutAdvisor

代码位置:org.springframework.aop.support.AbstractBeanFactoryPointcutAdvisor

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

BeanFactoryTransactionAttributeSourceAdvisor->TransactionAttributeSourcePointcut

回来这个:TransactionAttributeSourcePointcut

代码位置:org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut

这个类就是切面应用到事务中来的实现。重点、重点、重点

代码语言:javascript
复制
//是一个抽象类,继承自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

下面这个就比较简单了。就是返回一个包含TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME的字符串数组。配置事务管理和代理时使用。事务管理是指对数据库事务的管理,而代理是指在方法调用前后添加额外的逻辑处理。

代码语言:javascript
复制
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";

注解是如何使用的?

我们都知道我们在spring体系中是使用了@Transactional这个注解来启动事务。

上文有讲过关于advisor,其实spring事务也是引用了aop的思想进行切面的实现逻辑。只是有自已的独特逻辑。

代码位置:org.springframework.aop.framework.autoproxy.BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans

代码语言:javascript
复制
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

通过该注解进行启用事务。那么在前面的TransactionAttributeSourcePointcut.matches中会去识别是不是带了@Transactional注解,如果带了就是意味着启用事务。

前面初始化的逻辑与aop类似可以查看下aop的,这里不详细深入。

代码位置:org.springframework.aop.support.AopUtils#canApply(org.springframework.aop.Pointcut, java.lang.Class<?>)

代码语言:javascript
复制
//用于判断给定的类是否适用于指定的切点(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;
            }
        }
    }

注意这里:TransactionAttributeSourcePointcut.matches

这个方法就是刚刚前面初始化的时候实现的。这个就是用来判断是否为事务还是纯的aop。

代码语言:javascript
复制
@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

代码语言:javascript
复制
//重写了某个接口或者父类的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;
    }
  }

注意一下其中的:TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);

实现如下:

代码语言:javascript
复制
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;
  }

上面的逻辑是->判断为public->去目标事务注解中找->去接口上面找->去接口实现类上面找

代理的实现

那么下面需要了解一下事务是如何去代理实现的。其实spring调用开始前面一大段都跟aop一样,只是在调用中需要去判断是哪种代理、aop还是cglib或是引入的框架。

这里跳下逻辑,因为与前面的aop类型直接到这个类:TransactionAspectSupport

代码位置:org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction

代码语言:javascript
复制
//代理调用模版
  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;
      }
    }
  }

其实上面的逻辑就是 创建事务->执行事务->回滚/完成事务

看下里面这个方法:TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);

代码语言:javascript
复制
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);
  }

代码中:status = tm.getTransaction(txAttr);

代码位置:org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction

代码语言:javascript
复制
@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);
    }
  }

关于事务的传播行为请自行百茺或看文章:spring事务管理

接着代码: doBegin(transaction, definition);

有三个实现。这里用的是第二个。

org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

代码语言:javascript
复制
//
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);
        }
    }

上面的逻辑还是比较易懂的。比竟只要学完jdbc基本都看得懂。

最后还有一种事务是嵌套事务,那么这种也了解一下。

回到刚才这个位置:org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction中的

代码语言:javascript
复制
if (isExistingTransaction(transaction)) {
      // Existing transaction found -> check propagation behavior to find out how to behave.
      return handleExistingTransaction(definition, transaction, debugEnabled);
    }
代码语言:javascript
复制
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);
  }

这些操作实最终都会被doComit()

如果失败则进行回滚。

最后

Spring事务管理的核心思想是将事务的控制与业务逻辑分离,使得业务代码不需要关注事务的开启、提交或回滚等细节。通过使用Spring的事务管理器和声明式事务配置,可以将事务逻辑从业务代码中解耦,提供了更加灵活和简便的事务管理方式。相对来说spring事务比aop更加复杂,需要有aop+jdbc的基础。本文相对来说比较片面,可能理解起来不是很好,如果实在看不懂,建议参考下面的文章,对比看。

参考文章:

https://juejin.cn/post/6887751198737170446

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

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

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-08-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 技术趋势 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • spring事务的实现原理
    • Spring事务的工作原理如下:
    • spring事务源码学习
      • @EnableTransactionManagement注解
        • 注解是如何使用的?
          • 代理的实现
          • 最后
          相关产品与服务
          云顾问
          云顾问(Tencent Cloud Smart Advisor)是一款提供可视化云架构IDE和多个ITOM领域垂直应用的云上治理平台,以“一个平台,多个应用”为产品理念,依托腾讯云海量运维专家经验,助您打造卓越架构,实现便捷、灵活的一站式云上治理。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档