zoukankan      html  css  js  c++  java
  • Spring TX 原理

    调试环境:https://gitee.com/jhxxb/MySpringBoot/tree/master/spring-base/Spring-Transaction

    源码

    从 @EnableTransactionManagement 开始

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Import(TransactionManagementConfigurationSelector.class) // 导入组件
    public @interface EnableTransactionManagement {
    
        /**
         * 代理方式,CGLIB 动态代理和 JDK 动态代理
         */
        boolean proxyTargetClass() default false;
    
        /**
         * 代理方式:默认是 PROXY 采用 Spring 的动态代理(含 JDK 动态代理和 CGLIB 动态代理)
         * 若改为:AdviceMode.ASPECTJ 表示使用 AspectJ 静态代理方式。
         * 它能够解决同类内方法调用不走代理对象的问题,但是一般情况下都不建议这么去做,不要修改这个参数值
         */
        AdviceMode mode() default AdviceMode.PROXY;
    
        /**
         * 顺序,可能有多个 @EnableXXX
         */
        int order() default Ordered.LOWEST_PRECEDENCE;
    }

    TransactionManagementConfigurationSelector 的父类 AdviceModeImportSelector

    可以看到还有 Cache 和 Async

    public abstract class AdviceModeImportSelector<A extends Annotation> implements ImportSelector {
        /**
         * 默认都叫 mode
         */
        public static final String DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME = "mode";
    
        /**
         * 允许子类覆盖此方法
         */
        protected String getAdviceModeAttributeName() {
            return DEFAULT_ADVICE_MODE_ATTRIBUTE_NAME;
        }
    
        /**
         * @param importingClassMetadata 注解的信息
         */
        @Override
        public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
            // 这里泛型,拿到泛型类型
            Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
            Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");
    
            // 根据类型,拿到该类型的这个注解,然后转换为 AnnotationAttributes
            AnnotationAttributes attributes = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
            if (attributes == null) {
                throw new IllegalArgumentException(String.format("@%s is not present on importing class '%s' as expected", annType.getSimpleName(), importingClassMetadata.getClassName()));
            }
    
            // 拿到 AdviceMode,最终交给子类,让它自己去实现,决定导入哪个 Bean
            AdviceMode adviceMode = attributes.getEnum(getAdviceModeAttributeName());
            String[] imports = selectImports(adviceMode);
            if (imports == null) {
                throw new IllegalArgumentException("Unknown AdviceMode: " + adviceMode);
            }
            return imports;
        }
    
        /**
         * 子类去实现,具体导入哪个 Bean
         */
        @Nullable
        protected abstract String[] selectImports(AdviceMode adviceMode);
    }

    这里只看 TransactionManagementConfigurationSelector 实现

    public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
        @Override
        protected String[] selectImports(AdviceMode adviceMode) {
            // 绝大部分情况下都不会使用 AspectJ 的静态代理
            switch (adviceMode) {
                case PROXY:
                    // 这里会导入两个类
                    return new String[]{AutoProxyRegistrar.class.getName(), ProxyTransactionManagementConfiguration.class.getName()};
                case ASPECTJ:
                    return new String[]{determineTransactionAspectClass()};
                default:
                    return null;
            }
        }
    
        private String determineTransactionAspectClass() {
            return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
                    TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME : TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
        }
    }

    TransactionManagementConfigurationSelector 中导入的 AutoProxyRegistrar,主要是向 Spring 容器注入了一个自动代理创建器:org.springframework.aop.config.internalAutoProxyCreator,并且看看是采用 CGLIB 还是 JDK 代理。

    跟踪 AopConfigUtils 的源码可以看到,事务这块向容器注入的是一个 InfrastructureAdvisorAutoProxyCreator,它主要是读取 Advisor 类。

    /**
     * 实现了 ImportBeanDefinitionRegistrar 接口,可以向容器里注册 Bean 的定义信息
     */
    public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
    
        private final Log logger = LogFactory.getLog(getClass());
    
        @Override
        public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
            boolean candidateFound = false;
            // 这里是拿到所有的注解类型,而不是只拿 @EnableAspectJAutoProxy 这个类型的
            // 原因:因为 mode、proxyTargetClass 等属性会直接影响到代理的方式,而拥有这些属性的注解至少有:
            // @EnableTransactionManagement、@EnableAsync、@EnableCaching 等
            // 甚至还有启用 AOP 的注解:@EnableAspectJAutoProxy,它也能设置`proxyTargetClass`这个属性的值,因此也会产生关联影响
            Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
            for (String annType : annTypes) {
                AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
                if (candidate == null) {
                    continue;
                }
                // 拿到注解里的这两个属性,说明:如果你是比如 @Configuration 或者别的注解的话,它们就是 null 了
                Object mode = candidate.get("mode");
                Object proxyTargetClass = candidate.get("proxyTargetClass");
                // 如果存在 mode 和 proxyTargetClass 属性,且两个属性的 class 类型也是对的,才会进来此处(因此其余注解都挡外面了)
                if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() && Boolean.class == proxyTargetClass.getClass()) {
                    candidateFound = true; // 标志:找到了候选的注解
                    if (mode == AdviceMode.PROXY) {
                        // 这一步是非常重要的,AopConfigUtils 工具类的 registerAutoProxyCreatorIfNecessary 方法
                        // 它主要是注册了一个`internalAutoProxyCreator`,但是若出现多次的话,这里不是覆盖的形式,而是以第一次的为主
                        // 当然它内部有做等级的提升之类的
                        AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
                        if ((Boolean) proxyTargetClass) { // 看要不要强制使用 CGLIB 的方式(由此可以发现,这个属性若出现多次,是会以覆盖的形式)
                            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
                            return;
                        }
                    }
                }
            }
            // 如果一个都没有找到,可能是自己注入这个类,而不是使用注解注入的(不建议这么做)
            if (!candidateFound && logger.isInfoEnabled()) {
                String name = getClass().getSimpleName();
                // 输出 info 日志,不是 error 日志
                logger.info(String.format("%s was imported but no annotations were found having both 'mode' and 'proxyTargetClass' attributes of type AdviceMode and boolean respectively. This means that auto proxy " +
                       "creator registration and configuration may not have occurred as intended, and components may not be proxied as expected. Check to ensure that %s has been @Import'ed on the same class where these"
                       + " annotations are declared; otherwise remove the import of %s altogether.", name, name, name));
            }
        }
    }

    TransactionManagementConfigurationSelector 中导入的 ProxyTransactionManagementConfiguration,是个配置类

    @Configuration(proxyBeanMethods = false)
    @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
    public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
    
        // 这个 Advisor 是事务的核心内容
        @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
            BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
            advisor.setTransactionAttributeSource(transactionAttributeSource);
            advisor.setAdvice(transactionInterceptor);
            if (this.enableTx != null) { // 顺序由 @EnableTransactionManagement 注解的 Order 属性来指定,默认值为:Ordered.LOWEST_PRECEDENCE
                advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
            }
            return advisor;
        }
    
        // 这里直接使用的是 AnnotationTransactionAttributeSource,基于注解的事务属性源
        @Bean
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public TransactionAttributeSource transactionAttributeSource() {
            return new AnnotationTransactionAttributeSource();
        }
    
        // 事务拦截器,是个`MethodInterceptor`,它也是 Spring 处理事务最为核心的部分
        // 请注意:你可以自己定义一个 TransactionInterceptor(同名的),来覆盖此 Bean(注意是覆盖)
        // 另外请注意:你自定义的 BeanName 必须同名,也就是必须名为:transactionInterceptor,否则两个都会注册进容器里面去
        @Bean
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
            TransactionInterceptor interceptor = new TransactionInterceptor();
            // 事务的属性
            interceptor.setTransactionAttributeSource(transactionAttributeSource);
            // 事务管理器(也就是注解最终需要使用的事务管理器,父类已经处理好了)
            // 此处注意:我们是可以不用特殊指定的,最终它自己会去容器匹配一个适合的
            if (this.txManager != null) {
                interceptor.setTransactionManager(this.txManager);
            }
            return interceptor;
        }
    }

    ProxyTransactionManagementConfiguration 的抽象父类 AbstractTransactionManagementConfiguration 

    /**
     * 抽象父类,实现了 ImportAware 接口,可以拿到 @Import 所在类的所有注解信息
     */
    @Configuration
    public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
    
        @Nullable
        protected AnnotationAttributes enableTx;
    
        /**
         * 此处:注解的默认事务处理器(可以通过实现接口 TransactionManagementConfigurer 来自定义配置)
         * 因为事务管理器这个东西,一般来说全局一个就行,但是 Spring 也提供了定制化的能力
         */
        @Nullable
        protected TransactionManager txManager;
    
        @Override
        public void setImportMetadata(AnnotationMetadata importMetadata) {
            // 只拿 @EnableTransactionManagement 注解,作为 AnnotationAttributes 保存起来
            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());
            }
        }
    
        /**
         * 配置类可以实现这个接口。改变默认的事务管理器
         */
        @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();
        }
    
        /**
         * 注册一个监听器工厂,用以支持 @TransactionalEventListener 注解标注的方法,来监听事务相关的事件
         * 通过事件监听模式来实现事务的监控
         */
        @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
        @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
        public static TransactionalEventListenerFactory transactionalEventListenerFactory() {
            return new TransactionalEventListenerFactory();
        }
    }

    ProxyTransactionManagementConfiguration 中注入的 AnnotationTransactionAttributeSource,指定拦截标注有 @Transaction 注解的方法

    public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable {
        // 这个是“向下兼容”,JavaEE 提供的其余两种注解
        private static final boolean jta12Present; // JTA 1.2事务注解
        private static final boolean ejb3Present; // EJB 3 事务注解
    
        static {
            ClassLoader classLoader = org.springframework.transaction.annotation.AnnotationTransactionAttributeSource.class.getClassLoader();
            jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
            ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
        }
    
        // true:只处理 public 方法(基于 JDK 的代理,只能处理 public 方法)
        // false:private/protected 等方法都会处理。基于 AspectJ 代理的方式可以设置为 false
        // 默认情况下:会被赋值为 true,表示只处理 public 的方法
        private final boolean publicMethodsOnly;
    
        // 保存用于分析事务注解的事务注解分析器,这个注解分析的解析器是重点
        private final Set<TransactionAnnotationParser> annotationParsers;
    
    
        /**
         * 构造函数, publicMethodsOnly 缺省使用 true
         */
        public AnnotationTransactionAttributeSource() {
            this(true);
        }
    
        public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
            this.publicMethodsOnly = publicMethodsOnly;
            if (jta12Present || ejb3Present) {
                this.annotationParsers = new LinkedHashSet<>(4);
                this.annotationParsers.add(new SpringTransactionAnnotationParser());
                if (jta12Present) {
                    this.annotationParsers.add(new JtaTransactionAnnotationParser());
                }
                if (ejb3Present) {
                    this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
                }
            } else { // 默认情况下,只添加 Spring 自己的注解解析器(绝大部分情况都是进入这里)
                this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
            }
        }
    
        // 自己也可以指定一个 TransactionAnnotationParser,或者多个
        public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) {
            this.publicMethodsOnly = true;
            Assert.notNull(annotationParser, "TransactionAnnotationParser must not be null");
            this.annotationParsers = Collections.singleton(annotationParser);
        }
        public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) {
            this.publicMethodsOnly = true;
            Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
            this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
        }
        public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers) {
            this.publicMethodsOnly = true;
            Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
            this.annotationParsers = annotationParsers;
        }
    
        @Override
        public boolean isCandidateClass(Class<?> targetClass) {
            for (TransactionAnnotationParser parser : this.annotationParsers) {
                if (parser.isCandidateClass(targetClass)) {
                    return true;
                }
            }
            return false;
        }
    
        // 获取某个类/方法上的事务注解属性(属于父类的抽象方法)
        @Override
        @Nullable
        protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
            return determineTransactionAttribute(clazz);
        }
        @Override
        @Nullable
        protected TransactionAttribute findTransactionAttribute(Method method) {
            return determineTransactionAttribute(method);
        }
    
        /**
         * 分析获取某个被注解的元素(AnnotatedElement),具体来讲,指的是一个类或者一个方法上的事务注解属性。
         * 实现会遍历自己属性 annotationParsers 中所包含的事务注解属性,分析器试图获取事务注解属性,主要还是依赖于 TransactionAnnotationParser 去解析
         */
        @Nullable
        protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
            for (TransactionAnnotationParser parser : this.annotationParsers) {
                TransactionAttribute attr = parser.parseTransactionAnnotation(element);
                if (attr != null) {
                    return attr;
                }
            }
            return null;
        }

    AnnotationTransactionAttributeSource 的父类 AbstractFallbackTransactionAttributeSource

    public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
    
        /**
         * 针对没有事务注解属性的方法,进行事务注解属性缓存时使用的特殊值,用于标记该方法没有事务注解属性
         * 从而不用在首次缓存信息后,再次重复执行分析,来提高查找的效率
         * 标注了 @Transaction 注解的表示有事务属性的,才会最终加入事务。此处需要注意的是,只要被事务的 Advisor 切中的,都会缓存起来
         */
        @SuppressWarnings("serial")
        private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() {
            @Override
            public String toString() {
                return "null";
            }
        };
    
        /**
         * 方法上的事务注解属性缓存,key 使用目标类上的方法,使用类型 MethodClassKey 来表示
         * 这个 Map 会比较大,会被事务相关的 Advisor 拦截下来的方法,最终都会缓存下来
         * 因为会有很多,所以需要一个 NULL_TRANSACTION_ATTRIBUTE 常量来提高查找的效率
         */
        private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);
    
    
        /**
         * 获取指定方法上的注解事务属性,如果方法上没有注解事务属性,则使用目标方法所属类上的注解事务属性
         */
        @Override
        @Nullable
        public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
            if (method.getDeclaringClass() == Object.class) { // 如果目标方法是内部类 Object 上的方法,总是返回 null,这些方法上不应用事务
                return null;
            }
    
            // 先看缓存里有没有,此处使用的 MethodClassKey 作为 Map 的 key
            Object cacheKey = getCacheKey(method, targetClass);
            TransactionAttribute cached = this.attributeCache.get(cacheKey);
            if (cached != null) {
                // 目标方法上并没有事务注解属性,但是已经被尝试分析过并且已经被缓存
                // 使用的值是 NULL_TRANSACTION_ATTRIBUTE,所以这里再次尝试获取其注解事务属性时,直接返回 null
                if (cached == NULL_TRANSACTION_ATTRIBUTE) {
                    return null;
                } else {
                    return cached;
                }
            } else { // 缓存没有命中
                // 通过方法、目标 Class 分析出此方法上的事务属性
                TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
                if (txAttr == null) { // 如果目标方法上并没有使用注解事务属性,也缓存该信息,只不过使用的值是一个特殊值
                    this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
                } else {
                    // 获取 methodIdentification 基本是为了输出日志
                    String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
                    if (txAttr instanceof DefaultTransactionAttribute) {
                        ((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
                    }
                    if (logger.isTraceEnabled()) {
                        logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
                    }
                    // 存在目标属性就 put 进去。
                    this.attributeCache.put(cacheKey, txAttr);
                }
                return txAttr;
            }
        }
    
        /**
         * 查找目标方法上的事务注解属性,也是上面的核心方法
         */
        @Nullable
        protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
            // 如果事务注解属性分析仅仅针对 public 方法,而当前方法不是 public,则直接返回 null
            // 如果是 private,AOP 是能切入,代理对象也会生成的,但就是事务不会生效
            if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
                return null;
            }
    
            // 因为 Method 并不一样属于目标类。所以这个方法就是获取 targetClass 上的那个和 method 对应的方法,也就是最终要执行的方法
            Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
    
            // 第一步:去找直接标记在方法上的事务属性,如果方法上有就直接返回(不用再看类上的了)
            // findTransactionAttribute 这个方法由子类去实现的
            TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
            if (txAttr != null) {
                return txAttr;
            }
    
            // 然后尝试检查事务注解属性是否标记在目标方法 specificMethod(注意此处用不是 Method)所属类上
            txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
            if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                return txAttr;
            }
    
            // 程序走到这里说明目标方法 specificMethod,也就是实现类上的目标方法上没有标记事务注解属性(否则直接返回了)
            // 如果 specificMethod 和 method 不同,则说明 specificMethod 是具体实现类的方法,method 是实现类所实现接口的方法
            // 因此再次尝试从 method 上获取事务注解属性,这也就是为何我们的 @Transaction 标注在接口上或者接口的方法上都生效的原因
            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;
        }
    
        /**
         * 默认值是 false,表示 private 的也是 ok 的
         * 但`AnnotationTransactionAttributeSource`复写了它,可以由开发者指定(默认是 true 了)
         */
        protected boolean allowPublicMethodsOnly() {
            return false;
        }
    
        protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
            return new MethodClassKey(method, targetClass);
        }
    
        @Nullable
        protected abstract TransactionAttribute findTransactionAttribute(Class<?> clazz);
    
        @Nullable
        protected abstract TransactionAttribute findTransactionAttribute(Method method);
    }

    真正把 @Transaction 注解变成一个 TransactionAttribute 类的是 TransactionAnnotationParser,主要看 SpringTransactionAnnotationParser 实现,用于解析 Class 或者 Method 上的 org.springframework.transaction.annotation.Transactional 注解

     

    public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
    
        @Override
        public boolean isCandidateClass(Class<?> targetClass) {
            return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
        }
    
        /**
         * 此方法对外暴露,表示获取该方法/类上面的 TransactionAttribute
         */
        @Override
        @Nullable
        public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
            AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(element, Transactional.class, false, false);
            if (attributes != null) { // 把注解的属性交给 parseTransactionAnnotation 方法,最终转换为事务的属性类
                return parseTransactionAnnotation(attributes);
            } else { // 没有标注解就返回 null
                return null;
            }
        }
    
        /**
         * 重载方法,可以直接传入一个注解
         */
        public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
            return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
        }
    
        /**
         * 把注解上的属性转换为事务属性
         */
        protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
            // 此处用的 RuleBasedTransactionAttribute,因为它可以指定不需要回滚的类
            RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
    
            // 事务的传播属性枚举:内部定义了 7 种事务传播行为
            Propagation propagation = attributes.getEnum("propagation");
            rbta.setPropagationBehavior(propagation.value());
            // 事务的隔离级别枚举。一共是 4 种,枚举里提供一个默认值:TransactionDefinition.ISOLATION_DEFAULT
            // 至于默认值是哪种隔离界别,和具体的数据库有关
            Isolation isolation = attributes.getEnum("isolation");
            rbta.setIsolationLevel(isolation.value());
            // 设置事务的超时时间
            rbta.setTimeout(attributes.getNumber("timeout").intValue());
            // 是否是只读事务
            rbta.setReadOnly(attributes.getBoolean("readOnly"));
            // 这个属性,是指定事务管理器 PlatformTransactionManager 的 BeanName 的,若不指定,就按照类型找了
            // 若容器中存在多个事务管理器,但又没指定名字,那就报错
            rbta.setQualifier(attributes.getString("value"));
    
            // rollbackFor 可以指定需要回滚的异常,可以指定多个,若不指定默认为 RuntimeException
            // 此处使用的 RollbackRuleAttribute 包装,它就是个 POJO,没有实现 Spring 中的接口
            List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
            for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
                rollbackRules.add(new RollbackRuleAttribute(rbRule));
            }
            // 全类名的方式
            for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
                rollbackRules.add(new RollbackRuleAttribute(rbRule));
            }
    
            // 指定不需要回滚的异常类型
            // 此处使用的 NoRollbackRuleAttribute 包装,它是 RollbackRuleAttribute 的子类
            for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
                rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
            }
            for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
                rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
            }
    
            // 添加到 RuleBasedTransactionAttribute
            rbta.setRollbackRules(rollbackRules);
    
            return rbta;
        }

    ProxyTransactionManagementConfiguration 中注入的 BeanFactoryTransactionAttributeSourceAdvisor,是一个 Advisor,也就是 Pointcut 和 Advice 的组合

    public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
    
        @Nullable
        private TransactionAttributeSource transactionAttributeSource;
    
        /**
         * 这个很重要,就是切面。它决定了哪些类会被切入,从而生成的代理对象
         * 关于:TransactionAttributeSourcePointcut 下面有说
         */
        private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
            @Override
            @Nullable
            protected TransactionAttributeSource getTransactionAttributeSource() {
                return transactionAttributeSource;
            }
        };
    
        /**
         * 可以手动设置一个事务属性源
         */
        public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
            this.transactionAttributeSource = transactionAttributeSource;
        }
    
        /**
         * 可以指定 ClassFilter,默认情况下:ClassFilter classFilter = ClassFilter.TRUE; 匹配所有的类
         */
        public void setClassFilter(ClassFilter classFilter) {
            this.pointcut.setClassFilter(classFilter);
        }
    
        /**
         * 此处 pointcut 就是使用自己的这个 pointcut 去切入
         */
        @Override
        public Pointcut getPointcut() {
            return this.pointcut;
        }
    }

    BeanFactoryTransactionAttributeSourceAdvisor 中的 TransactionAttributeSourcePointcut,这个就是事务的 Pointcut 切面,决定了哪些类需要生成代理对象从而应用事务

    /**
     * 访问权限是 default,是 Spring 内部使用的
     * 继承自 StaticMethodMatcherPointcut,构造器调用了 setClassFilter 方法
     * 并且 isRuntime=false,表示只需要对方法进行静态匹配即可
     */
    abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
    
        protected TransactionAttributeSourcePointcut() {
            setClassFilter(new TransactionAttributeSourceClassFilter());
        }
    
        /**
         * 方法的匹配,静态匹配即可(事务不需要动态匹配那么细粒)
         * 关于 matches 方法的调用时机:只要是容器内的每个 Bean,都会经过 AbstractAutoProxyCreator#postProcessAfterInitialization,
         * 从而会调用 wrapIfNecessary 方法,因此容器内所有的 Bean 的所有方法在容器启动时候都会执行此 matche 方法
         */
        @Override
        public boolean matches(Method method, Class<?> targetClass) {
            TransactionAttributeSource tas = getTransactionAttributeSource();
            return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
        }
    
        /**
         * 由子类提供给,告诉事务属性源,好知道哪些方法需要切入
         */
        @Nullable
        protected abstract TransactionAttributeSource getTransactionAttributeSource();
    
        private class TransactionAttributeSourceClassFilter implements ClassFilter {
            @Override
            public boolean matches(Class<?> clazz) {
                // 实现了如下三个接口的子类,就不需要被代理了,直接放行
                // TransactionalProxy 是 SpringProxy 的子类。如果是被 TransactionProxyFactoryBean 生产出来的 Bean,就会自动实现此接口,那么就不会被这里再次代理了
                // PlatformTransactionManager:Spring 抽象的事务管理器
                // PersistenceExceptionTranslator:RuntimeException 转换成 DataAccessException 的转换接口
                if (TransactionalProxy.class.isAssignableFrom(clazz) ||
                        TransactionManager.class.isAssignableFrom(clazz) ||
                        PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
                    return false;
                }
                // 拿到事务属性源,如果 tas == null 表示没有配置事务属性源,那就是全部匹配的,也就是说所有的方法都匹配
                // 或者标注了 @Transaction 这样的注解的方法才会给与匹配
                TransactionAttributeSource tas = getTransactionAttributeSource();
                return (tas == null || tas.isCandidateClass(clazz));
            }
        }

    ProxyTransactionManagementConfiguration 中注入的 TransactionInterceptor,真正的执行事务方法

    在看 TransactionInterceptor 之前,先看下 Spring 事务管理中的 3 个高层抽象接口:

    • TransactionDefinition:用于描述隔离级别、超时时间、是否为只读事务和事务传播规则
    • TransactionStatus:代表一个事务的具体运行状态、以及还原点
    • PlatformTransactionManager:一个高层次的接口,包含3个方法。commit、rollback和getTramsaction

    TransactionStatus,事务代码可以使用它来检索状态信息,以编程方式请求回滚(而不是抛出导致隐式回滚的异常)

    public interface TransactionExecution {
        /**
         * 判断当前的事务是否是新事务
         */
        boolean isNewTransaction();
    
        /**
         * 事务的唯一结果是进行回滚。如果在外层给 try catche 住,不让事务回滚,就会抛出异常:
         * Transaction rolled back because it has been marked as rollback-only
         */
        void setRollbackOnly();
        boolean isRollbackOnly();
    
        /**
         * 不管是 commit 或者 rollback 了,都算结束了
         */
        boolean isCompleted();
    }
    
    /**
     * 表示事务的状态,继承自 SavepointManager,所以它也会处理还原点
     */
    public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
        /**
         * 判断该事务里面是否含有还原点
         */
        boolean hasSavepoint();
    
        /**
         * 将基础会话刷新到数据存储
         */
        @Override
        void flush();
    }

    抽象实现 AbstractTransactionStatus

    public abstract class AbstractTransactionStatus implements TransactionStatus {
        // 两个标志位
        private boolean rollbackOnly = false;
        private boolean completed = false;
    
        // 一个还原点
        @Nullable
        private Object savepoint;
    
        // 把该属性值保存为 true
        @Override
        public void setRollbackOnly() {
            this.rollbackOnly = true;
        }
    
        // 注意此处并不是直接读取
        @Override
        public boolean isRollbackOnly() {
            return (isLocalRollbackOnly() || isGlobalRollbackOnly());
        }
        public boolean isLocalRollbackOnly() {
            return this.rollbackOnly;
        }
    
        // Global 这里返回 false 但是子类 DefaultTransactionStatus 复写了此方法
        public boolean isGlobalRollbackOnly() {
            return false;
        }
    
        // 由子类去实现
        @Override
        public void flush() {
        }

    两个具体实现:SimpleTransactionStatus 和 DefaultTransactionStatus(Spring 默认使用的事务状态)

    // 就是标志一下事务是否是新的事务
    public class SimpleTransactionStatus extends AbstractTransactionStatus {
    
        private final boolean newTransaction;
    
        public SimpleTransactionStatus() {
            this(true);
        }
    
        public SimpleTransactionStatus(boolean newTransaction) {
            this.newTransaction = newTransaction;
        }
    
        @Override
        public boolean isNewTransaction() {
            return this.newTransaction;
        }
    }
    
    public class DefaultTransactionStatus extends AbstractTransactionStatus {
        @Nullable
        private final Object transaction;
        // 是否是新事务
        private final boolean newTransaction;
        // 如果为给定事务打开了新的事务同步,该值为 true
        private final boolean newSynchronization;
        // 该事务是否标记为了只读
        private final boolean readOnly;
        private final boolean debug;
    
        @Nullable
        private final Object suspendedResources;
    
        /**
         * 唯一构造函数
         */
        public DefaultTransactionStatus(@Nullable Object transaction, boolean newTransaction, boolean newSynchronization, boolean readOnly, boolean debug, @Nullable Object suspendedResources) {
            this.transaction = transaction;
            this.newTransaction = newTransaction;
            this.newSynchronization = newSynchronization;
            this.readOnly = readOnly;
            this.debug = debug;
            this.suspendedResources = suspendedResources;
        }
    
        /**
         * 直接把底层事务返回
         */
        public Object getTransaction() {
            Assert.state(this.transaction != null, "No transaction active");
            return this.transaction;
        }
    
        public boolean hasTransaction() {
            return (this.transaction != null);
        }
    
        @Override
        public boolean isNewTransaction() {
            return (hasTransaction() && this.newTransaction);
        }
    
        /**
         * 都由 SmartTransactionObject 去处理,该接口的实现类有:
         * JdbcTransactionObjectSupport 和 JtaTransactionObject(多数据源事务)
         */
        @Override
        public boolean isGlobalRollbackOnly() {
            return ((this.transaction instanceof SmartTransactionObject) && ((SmartTransactionObject) this.transaction).isRollbackOnly());
        }
    
        @Override
        public void flush() {
            if (this.transaction instanceof SmartTransactionObject) {
                ((SmartTransactionObject) this.transaction).flush();
            }
        }

    再看 TransactionInterceptor:事务拦截器,是个 MethodInterceptor,被事务拦截的方法最终都会执行到此增强器身上。MethodInterceptor 是个环绕通知,正好符合开启、提交、回滚事务等操作

    public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
        /**
         * 构造函数:
         * 可以不用特殊的指定 PlatformTransactionManager 事务管理器,后面会讲解自定义去获取
         * 可以自己指定 Properties 以及 TransactionAttributeSource
         */
        public TransactionInterceptor() {
        }
        public TransactionInterceptor(TransactionManager ptm, TransactionAttributeSource tas) {
            setTransactionManager(ptm);
            setTransactionAttributeSource(tas);
        }
        @Deprecated
        public TransactionInterceptor(PlatformTransactionManager ptm, TransactionAttributeSource tas) {
            setTransactionManager(ptm);
            setTransactionAttributeSource(tas);
        }
        @Deprecated
        public TransactionInterceptor(PlatformTransactionManager ptm, Properties attributes) {
            setTransactionManager(ptm);
            setTransactionAttributes(attributes);
        }
    
        // invoke 方法:拦截的入口
        @Override
        @Nullable
        public Object invoke(MethodInvocation invocation) throws Throwable {
            // 获取目标类
            Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    
            // invokeWithinTransaction:父类 TransactionAspectSupport 的模板方法
            // invocation::proceed 本处执行完成执行目标方法(当然可能还有其余增强器)
            return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
        }

    可以看出,真正做事的是父类 TransactionAspectSupport,它有一个执行事务的模版

    /**
     * 通过 BeanFactoryAware 获取到 BeanFactory
     * InitializingBean 的 afterPropertiesSet 是对 Bean 做一些验证(经常会借助它这么来校验 Bean)
     */
    public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
        // 这个类不允许实现 Serializable 接口,请注意
        // NOTE: This class must not implement Serializable because it serves as base
        // class for AspectJ aspects (which are not allowed to implement Serializable)!
    
        private static final Object DEFAULT_TRANSACTION_MANAGER_KEY = new Object();
        private static final boolean vavrPresent = ClassUtils.isPresent("io.vavr.control.Try", TransactionAspectSupport.class.getClassLoader());
        private static final boolean reactiveStreamsPresent = ClassUtils.isPresent("org.reactivestreams.Publisher", TransactionAspectSupport.class.getClassLoader());
    
        /**
         * currentTransactionStatus() 方法依托于它
         */
        private static final ThreadLocal<TransactionInfo> transactionInfoHolder = new NamedThreadLocal<>("Current aspect-driven transaction");
    
        /**
         * 此方法是个静态方法,并且是 protected 的,说明只有子类能够调用,外部并不可以
         */
        @Nullable
        protected static TransactionInfo currentTransactionInfo() throws NoTransactionException {
            return transactionInfoHolder.get();
        }
    
        /**
         * 外部调用此 Static 方法,可议获取到当前事务的状态,从而可以手动来提交、回滚事务
         */
        public static TransactionStatus currentTransactionStatus() throws NoTransactionException {
            TransactionInfo info = currentTransactionInfo();
            if (info == null || info.transactionStatus == null) {
                throw new NoTransactionException("No transaction aspect-managed TransactionStatus in scope");
            }
            return info.transactionStatus;
        }
    
        @Nullable
        private final ReactiveAdapterRegistry reactiveAdapterRegistry;
        @Nullable
        private String transactionManagerBeanName; // 事务管理器的名称(若设置,会根据此名称去找到事务管理器)
        @Nullable
        private TransactionManager transactionManager;
        @Nullable
        private TransactionAttributeSource transactionAttributeSource;
        @Nullable
        private BeanFactory beanFactory;
        // 事务管理器可能会有多个,此处做了一个简单的缓存
        private final ConcurrentMap<Object, TransactionManager> transactionManagerCache = new ConcurrentReferenceHashMap<>(4);
        private final ConcurrentMap<Method, ReactiveTransactionSupport> transactionSupportCache = new ConcurrentReferenceHashMap<>(1024);
    
        protected TransactionAspectSupport() {
            if (reactiveStreamsPresent) {
                this.reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance();
            } else {
                this.reactiveAdapterRegistry = null;
            }
        }
    
        /**
         * 若传入的为 Properties,内部实际使用的是 NameMatchTransactionAttributeSource 去匹配的
         * 备注:若调用了此方法 transactionAttributeSource 就会被覆盖
         */
        public void setTransactionAttributes(Properties transactionAttributes) {
            NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
            tas.setProperties(transactionAttributes);
            this.transactionAttributeSource = tas;
        }
    
        /**
         * 若有多种匹配策略,这也是支持的
         */
        public void setTransactionAttributeSources(TransactionAttributeSource... transactionAttributeSources) {
            this.transactionAttributeSource = new CompositeTransactionAttributeSource(transactionAttributeSources);
        }
    
        public void setTransactionAttributeSource(@Nullable TransactionAttributeSource transactionAttributeSource) {
            this.transactionAttributeSource = transactionAttributeSource;
        }
    
    
        /**
         * 处理事务的模版方法,protected 修饰,不允许其它包和无关类调用
         */
        @Nullable
        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 TransactionManager tm = determineTransactionManager(txAttr);
    
            if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
                ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
                    if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
                        throw new TransactionUsageException("Unsupported annotated transaction on suspending function detected: " + method + ". Use TransactionalOperator.transactional extensions instead.");
                    }
                    ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
                    if (adapter == null) {
                        throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + method.getReturnType());
                    }
                    return new ReactiveTransactionSupport(adapter);
                });
                return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
            }
    
            PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
            // 拿到目标方法唯一标识(类.方法,如 service.UserServiceImpl.save)
            final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    
            // 如果 txAttr 为空或者 tm 属于非 CallbackPreferringPlatformTransactionManager,执行目标增强
            // 在 TransactionManager 上,CallbackPreferringPlatformTransactionManager 实现 PlatformTransactionManager 接口,暴露出一个方法用于执行事务处理中的回调
            if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
                // 看是否有必要创建一个事务,根据`事务传播行为`,做出相应的判断
                TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
    
                Object retVal;
                try {
                    // 回调方法执行,执行目标方法(原有的业务逻辑)
                    retVal = invocation.proceedWithInvocation();
                } catch (Throwable ex) {
                    // 出现异常了,进行回滚(注意:并不是所有异常都会 rollback 的)
                    // 备注:此处若没有事务属性会 commit,兼容编程式事务
                    completeTransactionAfterThrowing(txInfo, ex);
                    throw ex;
                } finally {
                    // 清除信息
                    cleanupTransactionInfo(txInfo);
                }
    
                if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                    // Set rollback-only in case of Vavr failure matching our rollback rules...
                    TransactionStatus status = txInfo.getTransactionStatus();
                    if (status != null && txAttr != null) {
                        retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                    }
                }
                // 目标方法完全执行完成后,提交事务
                commitTransactionAfterReturning(txInfo);
                return retVal;
            }
    
            // 编程式事务处理(CallbackPreferringPlatformTransactionManager) 会走这里
            // 对于声明式事务的处理与编程式事务的处理,重要区别在于事务属性上,因为编程式的事务处理是不需要有事务属性的
            else {
                Object result;
                final ThrowableHolder throwableHolder = new ThrowableHolder();
    
                // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
                try {
                    result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
                        TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
                        try {
                            Object retVal = invocation.proceedWithInvocation();
                            if (retVal != null && vavrPresent && VavrDelegate.isVavrTry(retVal)) {
                                // Set rollback-only in case of Vavr failure matching our rollback rules...
                                retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
                            }
                            return retVal;
                        } catch (Throwable ex) {
                            if (txAttr.rollbackOn(ex)) {
                                // A RuntimeException: will lead to a rollback.
                                if (ex instanceof RuntimeException) {
                                    throw (RuntimeException) ex;
                                } else {
                                    throw new ThrowableHolderException(ex);
                                }
                            } else {
                                // A normal return value: will lead to a commit.
                                throwableHolder.throwable = ex;
                                return null;
                            }
                        } finally {
                            cleanupTransactionInfo(txInfo);
                        }
                    });
                } 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;
                }
    
                // Check result state: It might indicate a Throwable to rethrow.
                if (throwableHolder.throwable != null) {
                    throw throwableHolder.throwable;
                }
                return result;
            }
        }
    
        /**
         * 从容器中找到一个事务管理器
         */
        @Nullable
        protected TransactionManager determineTransactionManager(@Nullable TransactionAttribute txAttr) {
            // 如果这两个都没配置,那肯定是手动设置了 PlatformTransactionManager,直接返回即可
            if (txAttr == null || this.beanFactory == null) {
                return getTransactionManager();
            }
            // qualifier 相当于 BeanName
            String qualifier = txAttr.getQualifier();
            if (StringUtils.hasText(qualifier)) { // 根据此名称以及 PlatformTransactionManager.class 去容器内找
                return determineQualifiedTransactionManager(this.beanFactory, qualifier);
            } else if (StringUtils.hasText(this.transactionManagerBeanName)) { // 若没有指定 qualifier,那再看看是否指定了 transactionManagerBeanName
                return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName);
            } else { // 若都没指定,那就不管了。直接根据类型去容器里找 getBean(Class),此处若容器内有两个 PlatformTransactionManager,那就会报错
                TransactionManager defaultTransactionManager = getTransactionManager();
                if (defaultTransactionManager == null) {
                    defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
                    if (defaultTransactionManager == null) {
                        defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class);
                        this.transactionManagerCache.putIfAbsent(DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
                    }
                }
                return defaultTransactionManager;
            }
        }
    
        /**
         * 它是创建事务的一个重要方法
         * 它会判断是否存在事务,根据事务的传播属性。做出不同的处理,也是做了一层包装,核心是通过 TransactionStatus 来判断事务的属性
         * 若有需要,创建一个 TransactionInfo (具体的事务从事务管理器里面 getTransaction() 出来)
         */
        @SuppressWarnings("serial")
        protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
            // 给 Name 赋值
            if (txAttr != null && txAttr.getName() == null) {
                txAttr = new DelegatingTransactionAttribute(txAttr) {
                    @Override
                    public String getName() {
                        return joinpointIdentification;
                    }
                };
            }
    
            // 从事务管理器里,通过 txAttr 拿出来一个 TransactionStatus
            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");
                    }
                }
            }
            // 通过 TransactionStatus 等,转换成一个通用的 TransactionInfo
            return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
        }
    
        /**
         * 准备事务
         */
        protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, String joinpointIdentification, @Nullable TransactionStatus status) {
            // 构造一个 TransactionInfo
            TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
            if (txAttr != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
                }
                // 如果已存在不兼容的 Tx,事务管理器将标记错误
                txInfo.newTransactionStatus(status);
            } else {
                if (logger.isTraceEnabled()) {
                    logger.trace("No need to create transaction for [" + joinpointIdentification + "]: This method is not transactional.");
                }
            }
            // 这句话是最重要的:把生成的 TransactionInfo 绑定到当前线程的 ThreadLocal
            txInfo.bindToThread();
            return txInfo;
        }
    
        /**
         * 提交事务
         */
        protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
            // 用事务管理器提交事务即可,具体的实现逻辑在事务管理器的 commit 实现里
            if (txInfo != null && txInfo.getTransactionStatus() != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
                }
                txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
            }
        }
    
        /**
         * 回滚事务
         */
        protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
            if (txInfo != null && txInfo.getTransactionStatus() != null) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex);
                }
                // 如果有事务属性,那就调用 rollbackOn 看看这个异常需不需要回滚
                if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
                    try {
                        txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
                    } catch (TransactionSystemException ex2) {
                        logger.error("Application exception overridden by rollback exception", ex);
                        ex2.initApplicationException(ex);
                        throw ex2;
                    } catch (RuntimeException | Error ex2) {
                        logger.error("Application exception overridden by rollback exception", ex);
                        throw ex2;
                    }
                } else { // 编程式事务没有事务属性,那就 commit
                    try {
                        txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
                    } catch (TransactionSystemException ex2) {
                        logger.error("Application exception overridden by commit exception", ex);
                        ex2.initApplicationException(ex);
                        throw ex2;
                    } catch (RuntimeException | Error ex2) {
                        logger.error("Application exception overridden by commit exception", ex);
                        throw ex2;
                    }
                }
            }
        }
    
        /**
         * 清除(解绑)事务
         */
        protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) {
            if (txInfo != null) {
                txInfo.restoreThreadLocalStatus();
            }
        }
    
        /**
         * 内部类,事务 Info
         */
        protected static final class TransactionInfo {
            @Nullable
            private final PlatformTransactionManager transactionManager; // 当前事务的事务管理器
            @Nullable
            private final TransactionAttribute transactionAttribute; // 当前事务的事务属性
            private final String joinpointIdentification; // joinpoint 标识
            @Nullable
            private TransactionStatus transactionStatus; // 当前事务的 TransactionStatus
            // 重点就是这个 oldTransactionInfo 字段
            // 这个字段保存了当前事务所在的`父事务`上下文的引用,构成了一个链,准确的说是一个有向无环图
            @Nullable
            private TransactionInfo oldTransactionInfo;
    
            public TransactionInfo(@Nullable PlatformTransactionManager transactionManager,
                                   @Nullable TransactionAttribute transactionAttribute, String joinpointIdentification) {
                this.transactionManager = transactionManager;
                this.transactionAttribute = transactionAttribute;
                this.joinpointIdentification = joinpointIdentification;
            }
    
            public PlatformTransactionManager getTransactionManager() {
                Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
                return this.transactionManager;
            }
    
            // 注意这个方法名,新的一个事务 status
            public void newTransactionStatus(@Nullable TransactionStatus status) {
                this.transactionStatus = status;
            }
    
            public boolean hasTransaction() {
                return (this.transactionStatus != null);
            }
    
            // 绑定当前正在处理的事务的所有信息到 ThreadLocal
            private void bindToThread() {
                // 老的事务先从线程中拿出来,再把新的(也就是当前)绑定进去
                this.oldTransactionInfo = transactionInfoHolder.get();
                transactionInfoHolder.set(this);
            }
    
            private void restoreThreadLocalStatus() {
                // 当前事务处理完之后,恢复父事务上下文
                transactionInfoHolder.set(this.oldTransactionInfo);
            }

    最后看 PlatformTransactionManager:事务管理器,谈到事务,肯定是离不开它的。

    关于事务管理器,不管是 JPA(JpaTransactionManager )还是 JDBC(DataSourceTransactionManager)甚至是 JTA(JtaTransactionManager)等都实现自接口 PlatformTransactionManager

    先看抽象实现 AbstractPlatformTransactionManager,是一个非常典型的模版实现,各个方法实现都是这样。自己先提供实现模版,很多具体的实现方案都开放给子类,比如 begin,suspend, resume, commit, rollback 等,相当于留好了众多的连接点

    public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
        public static final int SYNCHRONIZATION_ALWAYS = 0; // 始终激活事务同步(请参阅事务的传播属性)
        public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1; // 仅对实际事务(即,不针对由传播导致的空事务)激活事务同步不支持现有后端事务
        public static final int SYNCHRONIZATION_NEVER = 2; // 永远不激活事务同步
        // 相当于把本类的所有 public static final 的变量都收集到此处
        private static final Constants constants = new Constants(AbstractPlatformTransactionManager.class);
        protected transient Log logger = LogFactory.getLog(getClass());
        private int transactionSynchronization = SYNCHRONIZATION_ALWAYS;
        private int defaultTimeout = TransactionDefinition.TIMEOUT_DEFAULT;
        private boolean nestedTransactionAllowed = false;
        private boolean validateExistingTransaction = false;
        // 设置是否仅在参与事务`失败后`将现有事务`全局`标记为回滚,默认值是 true
        // 表示只要你的事务失败了,就标记此事务为 rollback-only,表示它只能回滚,不能再 commit 或者正常结束了
        // 这个调用者经常会犯的一个错误就是:上层事务 service 抛出异常了,自己把它给 try 住,并且还不 throw,那就肯定会报错的:
        // 报错信息:Transaction rolled back because it has been marked as rollback-only
        // 这个属性强制不建议设置为 false
        private boolean globalRollbackOnParticipationFailure = true;
        private boolean failEarlyOnGlobalRollbackOnly = false; // 如果事务被全局标记为仅回滚,则设置是否及早失败
        private boolean rollbackOnCommitFailure = false; // 设置在 docommit 调用失败时是否应执行 dorollback,通常不需要,因此应避免
    
        /**
         * 使用起来有点枚举的意思了,这也是 Constants 的重要意义
         */
        public final void setTransactionSynchronizationName(String constantName) {
            setTransactionSynchronization(constants.asNumber(constantName).intValue());
        }
    
        /**
         * 最为重要的一个方法,根据定义,获取到一个事务 TransactionStatus
         */
        @Override
        public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
            // 如果没有配置事务属性,则使用默认的事务属性
            TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
    
            // doGetTransaction() 方法是抽象方法,具体的实现由具体的事务处理器提供
            Object transaction = doGetTransaction();
            boolean debugEnabled = logger.isDebugEnabled();
    
            if (isExistingTransaction(transaction)) { // 检查当前线程是否存在事务,isExistingTransaction 此方法默认返回 false,但子类都复写了此方法
                // handleExistingTransaction 方法为处理已经存在事务的情况,这个方法的实现也很复杂,总之还是对一些传播属性进行解析,各种情况的考虑,如果有新事务产生 doBegin() 就会被调用
                return handleExistingTransaction(def, transaction, debugEnabled);
            }
    
            if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { // 超时校验
                throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
            }
    
            // 处理事务属性中配置的事务传播特性
            // PROPAGATION_MANDATORY 如果已经存在一个事务,支持当前事务。如果没有一个活动的事务,则抛出异常
            if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
                throw new IllegalTransactionStateException("No existing transaction found for transaction marked with propagation 'mandatory'");
            } else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
                    def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
                    def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { // 如果事务传播特性为 required、required_new 或 nested
                // 挂起,但是 doSuspend() 由子类去实现
                // 挂起操作,触发相关的挂起注册的事件,把当前线程事物的所有属性都封装好,放到一个 SuspendedResourcesHolder
                // 然后清空一下`当前线程事务`
                SuspendedResourcesHolder suspendedResources = suspend(null);
                if (debugEnabled) {
                    logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
                }
                try { // 此处,开始创建事务
                    return startTransaction(def, transaction, debugEnabled, suspendedResources);
                } catch (RuntimeException | Error ex) { // 重新开始,里面的 doResume 由子类去实现
                    resume(null, suspendedResources);
                    throw ex;
                }
            } else { // 走到这里,传播属性就是不需要事务的,那就直接创建一个
                if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
                    logger.warn("Custom isolation level specified but no actual transaction initiated; isolation level will effectively be ignored: " + def);
                }
                boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
                // 这个方法相当于先 newTransactionStatus,再 prepareSynchronization 这两步
                // 显然和上面的区别是:中间不会插入调用 doBegin() 方法,因为没有事务
                return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
            }
        }
    
        /**
         * Start a new transaction.
         */
        private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction, boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
            boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
            // 创建一个新的事务状态,就是 new DefaultTransactionStatus(),把个属性都赋值上
            DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
            // 开始事务,抽象方法,由子类去实现
            doBegin(transaction, definition);
            // 初始化和同步事务状态,是 TransactionSynchronizationManager 这个类,它内部维护了很多的 ThreadLocal
            prepareSynchronization(status, definition);
            return status;
        }
    
        @Override
        public final void commit(TransactionStatus status) throws TransactionException {
            if (status.isCompleted()) { // 如果是一个已经完成的事物,不可重复提交
                throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
            }
    
            DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
            if (defStatus.isLocalRollbackOnly()) { // 如果已经标记为了需要回滚,那就执行回滚吧
                if (defStatus.isDebug()) {
                    logger.debug("Transactional code has requested rollback");
                }
                processRollback(defStatus, false);
                return;
            }
    
            // shouldCommitOnGlobalRollbackOnly 这个默认值是 false,目前只有 JTA 事务复写成 true 了
            // isGlobalRollbackOnly:是否标记为了全局的 RollbackOnly
            if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
                if (defStatus.isDebug()) {
                    logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
                }
                processRollback(defStatus, true);
                return;
            }
            // 提交事务,这里面还是挺复杂的,会考虑到还原点、新事务、事务是否是 rollback-only 之类的
            processCommit(defStatus);
        }
    
        @Override
        public final void rollback(TransactionStatus status) throws TransactionException {
            if (status.isCompleted()) {
                throw new IllegalTransactionStateException("Transaction is already completed - do not call commit or rollback more than once per transaction");
            }
    
            DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
            // 里面 doRollback 方法交给子类去实现
            processRollback(defStatus, false);
        }

    DataSourceTransactionManager 实现

    public class DataSourceTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, InitializingBean {
    
        @Nullable
        private DataSource dataSource; // 管理的是 DataSource,JTA 多数据源事务管理可能就是各种各样的数据源了
        private boolean enforceReadOnly = false; // 不要强制标记为 ReadOnly
    
        public DataSourceTransactionManager() {
            setNestedTransactionAllowed(true); // JDBC 默认是允许内嵌的事务的
        }
    
        public DataSourceTransactionManager(DataSource dataSource) {
            this();
            setDataSource(dataSource);
            afterPropertiesSet(); // InitializingBean 做了一个简单的校验
        }
    
        /**
         * 手动设置数据源
         */
        public void setDataSource(@Nullable DataSource dataSource) {
            if (dataSource instanceof TransactionAwareDataSourceProxy) { // TransactionAwareDataSourceProxy 是对 dataSource 的包装
                this.dataSource = ((TransactionAwareDataSourceProxy) dataSource).getTargetDataSource();
            } else {
                this.dataSource = dataSource;
            }
        }
    
        /**
         * 这里返回的是一个`DataSourceTransactionObject`
         * 它是一个`JdbcTransactionObjectSupport`,所以它是 SavepointManager、实现了 SmartTransactionObject 接口
         */
        @Override
        protected Object doGetTransaction() {
            DataSourceTransactionObject txObject = new DataSourceTransactionObject();
            txObject.setSavepointAllowed(isNestedTransactionAllowed());
            // 按照线程来获取
            ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
            txObject.setConnectionHolder(conHolder, false);
            return txObject;
        }
    
        @Override
        protected boolean isExistingTransaction(Object transaction) { // 检查当前事务是否 active
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
            return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
        }
    
        @Override
        protected void doBegin(Object transaction, TransactionDefinition definition) {
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
            Connection con = null;
    
            try {
                if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
                    // 从 DataSource 里获取一个连接(这个 DataSource 一般是有连接池的)
                    Connection newCon = obtainDataSource().getConnection();
                    if (logger.isDebugEnabled()) {
                        logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
                    }
                    // 把这个连接用 ConnectionHolder 包装一下
                    txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
                }
    
                txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
                con = txObject.getConnectionHolder().getConnection();
                // 设置 isReadOnly、设置隔离级别等
                Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
                txObject.setPreviousIsolationLevel(previousIsolationLevel);
                txObject.setReadOnly(definition.isReadOnly());
    
                // 这里非常的关键,先看看 Connection 是否是自动提交的
                // 如果是,就 con.setAutoCommit(false),要不然数据库默认每执行一条 SQL 都是一个事务,就没法进行事务的管理了
                if (con.getAutoCommit()) {
                    txObject.setMustRestoreAutoCommit(true);
                    if (logger.isDebugEnabled()) {
                        logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
                    }
                    con.setAutoCommit(false);
                }
    
                // 因此从这后面,通过此 Connection 执行的所有 SQL 语句只要没有 commit 就都不会提交给数据库
    
                // 这个方法特别特别有意思,它自己`Statement stmt = con.createStatement()`拿到一个 Statement
                // 然后执行了一句 SQL:`stmt.executeUpdate("SET TRANSACTION READ ONLY");`
                // 所以,所以:如果你仅仅只是查询。把事务的属性设置为 readonly=true,Spring 会帮你对 SQl 进行优化
                // 需要注意的是:readonly=true 后,只能读,不能进行 dml 操作)(只能看到设置事物前数据的变化,看不到设置事物后数据的改变)
                prepareTransactionalConnection(con, definition);
                txObject.getConnectionHolder().setTransactionActive(true);
    
                int timeout = determineTimeout(definition);
                if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
                    txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
                }
    
                // 这一步:就是把当前的链接 和当前的线程进行绑定
                if (txObject.isNewConnectionHolder()) {
                    TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
                }
            } catch (Throwable ex) {
                if (txObject.isNewConnectionHolder()) { // 如果是新创建的链接,那就释放
                    DataSourceUtils.releaseConnection(con, obtainDataSource());
                    txObject.setConnectionHolder(null, false);
                }
                throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
            }
        }
    
        @Override
        protected void doCommit(DefaultTransactionStatus status) { // 真正提交事务
            // 拿到连接,然后直接 commit
            DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
            Connection con = txObject.getConnectionHolder().getConnection();
            if (status.isDebug()) {
                logger.debug("Committing JDBC transaction on Connection [" + con + "]");
            }
            try {
                con.commit();
            } catch (SQLException ex) {
                throw new TransactionSystemException("Could not commit JDBC transaction", ex);
            }
        }

    https://blog.csdn.net/f641385712/article/details/89607829

    https://blog.csdn.net/f641385712/article/details/89673753

    https://blog.csdn.net/f641385712/article/details/89637176

  • 相关阅读:
    计算页数
    DOS批量拷贝文件
    时间与日期处理
    MOUSE_OVER/MOUSE_OUT与ROLL_OVER/ROLL_OUT的区别
    vb程序改写方法。
    sqldmo备份还原sqlserver2000数据库
    终于有了自己的窝啦
    vb中创建Excel,把数据存入Excel
    提高vb 》excel数据的导入速度
    SQLServer2000数据库特有的1433端口号不能访问
  • 原文地址:https://www.cnblogs.com/jhxxb/p/14137875.html
Copyright © 2011-2022 走看看