Spring原理【8】Spring组件实现篇(一)

Spring与事务处理

JavaEE应用中的事务处理是一个重要并且涉及范围很广的领域。对于读者已经很熟悉的ACID属性,这里就不做过多阐述了。事务管理的实现往往涉及并发和数据一致性方面的问题,具有这些方面的知识背景,可以增强对事务处理的理解。作为应用平台的Spring,具有在多种环境中配置和使用事务处理的能力,也就是说通过使用Spring的事务处理,可以把事务处理的工作统一起来,并为事务处理提供通用的支持。 由于这方面的内容比较多且比较复杂,因此本章只阐述一些在事务处理中最为基本的使用场景,即Spring是怎样实现对单个数据库局部事务的处理的。在涉及单个数据库局部事务的事务处理中,事务的最终实现和数据库的支持是紧密相关的。对局部数据库事务来说,一个事务处理的操作单元往往对应着一系列的数据库操作。数据库产品对这些数据库的SQL操作已经提供了原子性的支持,对SQL操作而言,它的操作结果有两种:一种是提交成功,数据库操作成功,另一种是回滚,数据库操作不成功,恢复到操作以前的状态。 在事务处理中,事务处理单元的设计与相应的业务逻辑设计有很紧密的联系。在很多情况下,不会只有一个单独的数据库操作,而是有一组数据库操作。在这个处理过程中,首先涉及的是事务处理单元划分的问题,Spring借助IoC容器的强大配置能力,为应用提供了声明式的事务划分方式,这种声明式的事务处理,为Spring应用使用事务管理提供了统一的方式。有了Spring事务管理的支持,只需要通过一些简单的配置,应用就能完成复杂的事务处理工作,从而为用户卢使用事务处理提供很大的方便。

Spring事务处理的设计概览

在Spring的事务处理模块中,可以看到的类层次结构如下图。

类继承关系说明:

(1)AbstractSingletonProxyFactoryBean继承ProxyConfig类,实现FactoryBean,BeanClassLoaderAware,InitializingBean接口;

(2)TransactionProxyFactoryBean继承AbstractSingletonProxyFactoryBean,实现BeanFactoryAware接口,实现的方法中包含TransactionInterceptor类型的参数;

(3)TransactionAspectSupport实现BeanFactory,InitializingBean接口;

(4)TransactionInterceptor继承TransactionAspectSupport,实现MethodInterceptor接口,实现的方法中包含PlatformTractionManager类型的参数;

(5)PlatformTransactionManager接口继承TransactionManager接口;

(6)AbstractPlatformTransactionManager实现PlatformTransactionManager接口;

(7)AbstractPlatformTransactionManager的实现类包括JtaTransactionManager,CciLocalTransactionManager,WebLogicJtaTransactionManager,WebSphereUowTransactionManager等。

从上图中可以看到,Spring事务处理模块是通过AOP功能来实现声明式事务处理的,比如事务属性的配置和读取,事务对象的抽象等。因此,在Spring事务处理中,可以通过设计一个TransactionProxyFactoryBean来使用AOP功能,通过这个TransactionProxyFactoryBean可以生成Proxy代理对象,在这个代理对象中,通过TransactionInterceptor来完成对代理方法的拦截,正是这些AOP的拦截功能,将事务处理的功能编织进来。在Spring事务处理中,在实现声明式事务处理时,这是AOP和IoC模块集成的部分。对于具体的事务处理实现,比如事务的生成、提交、回滚、挂起等,由于不同的底层数据库有不同的支持方式,因此,在Spring事务处理中,对主要的事务实现做了一个抽象和适配。适配的其体事务处理器包括:对DataSource数据源的事务处理支持,对Hibernate数据源的事务处理支持,对JDO数据源的事务处理支持,对JPA和JTA等数据源的事务处理支持等。这一系列的事务处理支持,都是通过设计PlatformTransactionManager、AbstractPlatforTransactionManager以及一系列具体事务处理器来实现的,而PlatformTransactionManager文实现了TransactionInterceptor接口,通过这样一个接口实现设计,就把这一系列的事务处理的实现与前面提到的TransactionProxyFactoryBean结合起来,从而形成了一个Spring声明式事务处理的设计体系。

Spring声明式事务处理

设计原理与基本过程

在使用Spring声明式事务处理的时候,一种常用的方法是结合IoC容器和Spring已有的TransactionProxyFactoryBean对事务管理进行配置,比如,可以在这个TransactionProxyFactoryBean中为事务方法配置传播行为、并发事务隔离级别等事务处理属性,从而对声明式事务的处理提供指导。具体来说,在以下的内容中,在对声明式事务处理的原理分析中,声明式事务处理的实现大致可以分为以下几个部分: (1)读取和处理在IoC容器中配置的事务处理属性,并转化为Spring事务处理需要的内部数据结构。具体来说,这里涉及的类是TransactionAttributeSourceAdvisor,从名字可以看出,它是一个AOP通知器,Spring使用这个通知器来完成对事务处理属性值的处理。处理的结果是,在IoC容器中配置的事务处理属性信息,会被读入并转化成TransactionAttribute表示的数据对象,这个数据对象是Spring对事物处理属性值的数据抽象,对这些属性的处理是和TransactionProxyFactoryBean拦截下来的事务方法的处理结合起来的。 (2)Spring事务处理模块实现统一的事务处理过程。这个通用的事务处理过程包含处理事务配置属性,以及与线程绑定完成事务处理的过程,Spring通过TransactionInfo和TransactionStatus这两个数据对象,在事务处理过程中记录和传递相关执行场景。 (3)底层的事务处理实现。对于底层的事务操作,Spring委托给具体的事务处理器来完成,这些具体的事务处理器,就是在IoC容器中配置声明式事务处理时,配置的PlatformTransactionManager的具体实现,比如DataSourceTransactionManager和HibernateTransactionManager等。这两个具体的事务处理器的实现原理也是本章分析的内容。

实现分析

1、事务处理拦截器的配置

和前面的思路一样,从声明式事务处理的基本用法入手,来了解它的基本实现原理。大家都已经很熟悉了,在使用声明式事务处理的时候,需要在IoC容器中配置TransactionProxyFactoryBean,这是一个FactoryBean,对于FactoryBean这个在Spring中经常使用的工厂Bean,大家一定不会陌生。看到FactoryBean,毫无疑向,会让大家立刻想起它的getObject()方法,但关于具体是怎样建立起事务处理的对象机制的,可以通过下面的时序图进行了解,如下图所示。在IoC容器进行注入的时候,会创建Transactionlnterceptor对象,而这个对象会创建一个TransactionAttributePointcut,为读取TransactionAttribute做准备。在容器初始化的过程中,由于实现了InitializingBean接口,因此AbstractSingletonProxyFactoryBean会实现afterPropertiesSet()方法,正是在这个方法实例化了一个ProxyFactory,建立起SpringAOP的应用,在这里,会为这个ProxyFactory设置通知、目标对象,并最终返回Proxy代理对象。在Proxy代理对象建立起来以后,在调用其代理方法的时候,会调用相应的TransactionInterceptor拦截器,在这个调用中,会根据TransactionAttribute配置的事务属性进行配置,从 而为事务处理做好准备。

建立事务处理对象的时序图(待补充)

从TransactionProxyFactoryBean入手,通过代码实现来了解Spring是如何通过AOP功能来完成事务管理配置的,具体时序图如下代码清单所示。从代码清单中可以看到,Spring为声明式事务处理的实现所做的一些准备工作:包括为AOP配置基础设施,这些基础设施包括设置拦截器TransactionInterceptor、通知器DefaultPointcutAdvisor或TransactionAttributeSourceAdvisor。同时,在TransactionProxyFactoryBean的实现中,还可以看到注入进来的PlatformTransactionManager和事务处理属性TransactionAttribute等。

typescript 复制代码
public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean
       implements BeanFactoryAware {
    // 这个拦截器TransactionInterceptor通过AOP返回作用,通过这个拦截器的实现,Spring封装了事务处理实现,关于它的具体实现,下面进行详细的分析
    private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

    @Nullable
    private Pointcut pointcut;
    
    // 通过依赖注入的PlatformTransactionManager
    public void setTransactionManager(PlatformTransactionManager transactionManager) {
       this.transactionInterceptor.setTransactionManager(transactionManager);
    }

    // 通过依赖注入的事务属性以Properties的形式出现,把从BeanDefinition中读取到的事务管理的属性注入到transactionInterceptor中
    public void setTransactionAttributes(Properties transactionAttributes) {
       this.transactionInterceptor.setTransactionAttributes(transactionAttributes);
    }

    public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
       this.transactionInterceptor.setTransactionAttributeSource(transactionAttributeSource);
    }

    public void setPointcut(Pointcut pointcut) {
       this.pointcut = pointcut;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) {
       this.transactionInterceptor.setBeanFactory(beanFactory);
    }


    /**
     * Creates an advisor for this FactoryBean's TransactionInterceptor.
     */
    @Override
    protected Object createMainInterceptor() {
       this.transactionInterceptor.afterPropertiesSet();
       if (this.pointcut != null) {
          // 这里使用默认的通知器DefaultPointcutAdvisor,并为通知器配置事务处理拦截器
          return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor);
       }
       else {
          // Rely on default pointcut.
          return new TransactionAttributeSourceAdvisor(this.transactionInterceptor);
       }
    }

    /**
     * As of 4.2, this method adds {@link TransactionalProxy} to the set of
     * proxy interfaces in order to avoid re-processing of transaction metadata.
     */
    @Override
    protected void postProcessProxyFactory(ProxyFactory proxyFactory) {
       proxyFactory.addInterface(TransactionalProxy.class);
    }
}

以上代码完成了AOP配置,对于用户来说,一个值得关心的问题是,Spring的TransactionInterceptor配置是在什么时候被启动并成为Advisor通知器的一部分的呢?从对createMainInterceptor方法的调用分析中可以看到,这个createMainInterceptor方法在IoC容器完成Bean的依赖注入时,通过initializeBean方法被调用,具体的调用过程如下图所示。

调用到TransactionProxyFactoryBean.createMainInterceptor的堆栈如下:

makefile 复制代码
createMainInterceptor:194, TransactionProxyFactoryBean (org.springframework.transaction.interceptor)
afterPropertiesSet:161, AbstractSingletonProxyFactoryBean (org.springframework.aop.framework) // 此处为AbstractSingletonProxyFactoryBean的InitializingBean接口的回调方法
invokeInitMethods:1863, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1800, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:620, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support) // 创建Bean的触发点
createBean:542, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
lambda$doGetBean$0:335, AbstractBeanFactory (org.springframework.beans.factory.support)
getObject:-1, 1607869297 (org.springframework.beans.factory.support.AbstractBeanFactory$$Lambda$40)
getSingleton:234, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:333, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:208, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:936, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:921, AbstractApplicationContext (org.springframework.context.support)
refresh:583, AbstractApplicationContext (org.springframework.context.support)
<init>:142, FileSystemXmlApplicationContext (org.springframework.context.support)
<init>:85, FileSystemXmlApplicationContext (org.springframework.context.support)
main:20, SpringTest (com.spring.tx)

在TransactionProxyFactoryBean中看到的afterPropertiesSet方法,是Spring事务处理完成AOP配置的地方,这个afterPropertiesSet方法的功能实现如下代码清单所示。在代码清单中可以看到,在建立TransactionProxyFactoryBean的事务处理拦截器的时候,首先需要对ProxyFactoryBean的目标Bean设置进行检查,如果这个目标Bean的设置是正确的,就会创建一个ProxyFactory对象,从而实现AOP的使用。在afterPropertiesSet的方法实现中,可以看到为ProxyFactory生成代理对象、配置通知器、设置代理接口方法等。

TransactionProxyFactoryBean中看到的afterPropertiesSet方法是父类AbstractSingletonProxyFactoryBean中实现的,org.springframework.aop.framework.AbstractSingletonProxyFactoryBean#afterPropertiesSet的实现如下:

kotlin 复制代码
public void afterPropertiesSet() {
    // 必须配置target的属性,同时需要target是一个bean reference
    if (this.target == null) {
       throw new IllegalArgumentException("Property 'target' is required");
    }
    if (this.target instanceof String) {
       throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value");
    }
    if (this.proxyClassLoader == null) {
       this.proxyClassLoader = ClassUtils.getDefaultClassLoader();
    }
    // TransactionProxyFactoryBean使用ProxyFactory完成AOP的基本功能,这个ProxyFactory提供Proxy对象,并将TransactionInterceptor设置为target方法调用的拦截器
    ProxyFactory proxyFactory = new ProxyFactory();

    if (this.preInterceptors != null) {
       for (Object interceptor : this.preInterceptors) {
          proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
       }
    }
    // 这里是Spring加入通知器的地方,可以加入两种通知器,分别是DefaultPointcutAdvisor和TransactionAttributeSourceAdvisor
    // 这里调用TransactionProxyFactoryBean的createMainInterceptor方法生成所需的Advisors
    // 在ProxyFactory的基类AdvisedSupport中,维护了一个用来持有advise的List,通过这个List来管理配置给ProxyFactory的通知器
    // Add the main interceptor (typically an Advisor).
    proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor()));

    if (this.postInterceptors != null) {
       for (Object interceptor : this.postInterceptors) {
          proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor));
       }
    }

    proxyFactory.copyFrom(this);
    // 这里创建AOP的目标源,与在其他地方的使用类似
    TargetSource targetSource = createTargetSource(this.target);
    proxyFactory.setTargetSource(targetSource);

    if (this.proxyInterfaces != null) {
       proxyFactory.setInterfaces(this.proxyInterfaces);
    }
    else if (!isProxyTargetClass()) {
       // 需要根据AOP基础设施来确定使用哪个接口作为代理
       // Rely on AOP infrastructure to tell us what interfaces to proxy.
       Class<?> targetClass = targetSource.getTargetClass();
       if (targetClass != null) {
          proxyFactory.setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
       }
    }

    postProcessProxyFactory(proxyFactory);
    // 设置代理对象
    this.proxy = proxyFactory.getProxy(this.proxyClassLoader);
}

org.springframework.aop.framework.ProxyCreatorSupport#createAopProxy的实现如下,用于生成AopProxy:

kotlin 复制代码
protected final synchronized AopProxy createAopProxy() {
    if (!this.active) {
       activate();
    }
    // 使用DefaultAopProxyFactory来创建AopProxy
    // 因为这个ProxyAopCreator类本身就是ProxyConfig的子类,所以这里创建AopProxy的过程和其他类似
    return getAopProxyFactory().createAopProxy(this);
}

DefaultAopProxyFactory创建AOPProxy的过程在前面分析AOP的实现原理时已经分析过了,这里就不再重复了。可以看到,通过以上的一系列步骤,Spring为实现事务处理而设计的拦截器TransctionInterceptor已经设置到ProxyFactory生成的AOP代理对象中去了,这里的TransactionInterceptor是作为AOPAdvice的拦截器来实现它的功能的。在IoC容器中,配置其他与事务处理有关的属性,比如,比较熟悉的transactionManager和事务处理的属性,也同样会被设置到已经定义好的TransactionInterceptor中去。这些属性配置在TransactionInterceptor对事务方法进行拦截时会起作用。在AOP配置完成以后,可以看到,在Spring声明式事务处理实现中的一些重要的类已经俏然登场,比如TransactionAttributeSourceAdvisor和Transactionlnterceptor。正是这些类通过AOP封装了Spring对事务处理的基本实现,有了这些基础的知识,下面就可以详细地分析这些类的具体实现,

2、事务处理配置的读入

在AOP配置完成的基础上,以TransactionAttributeSourceAdvisor的实现为入口,了解具体的事务属性配置是如何读入的,具体实现如下代码清单所示。

org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor中定义TransactionInterceptor的实现如下:

less 复制代码
// 与其他advisor一样,同样需要定义AOP中用到的Interceptor和PointCut
	private TransactionInterceptor transactionInterceptor;


	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
	    // 这里通过transactionInterceptor来得到事务的配置属性,在对Proxy的方法进行匹配调用时,会使用到这些配置属性
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return (transactionInterceptor != null ? transactionInterceptor.getTransactionAttributeSource() : null);
		}
	};

在声明式事务处理中,通过对目标对象的方法调用进行拦截实现,这个拦截通过AOP发挥作用。在AOP中,对于拦截的启动,首先需要对方法调用是否需要挡截进行判断,而判断的依据那些在TransactionProxyFactoryBean中为目标对象设置的事务属性。也就是说,需要判断当前的目标方法调用是不是一个配置好的并且需要进行事务处理的方法调用。具体来说,这个匹配判断在TransactionAttributeSourcePointcut中完成,它的实现如下代码清单所示。在代码清单中,可以看到在AOP的Pointcut类中的一个matches方法,这个matches方法的实现原理在前面的AOP实现中已经做过分析。在这个为事务处理服务的TransactionAttributeSourcePointcut的matches方法实现中,首先把事务方法的属性配置读取到TransactionAttributeSource对象中,有了这些事务处理的配置以后,根据当前方法调用的Method对象和目标对象,对是否需要启动事务处理拦截器进行判断。

org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches的实现如下:

sql 复制代码
public boolean matches(Method method, Class<?> targetClass) {
    TransactionAttributeSource tas = getTransactionAttributeSource();
    return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

在Pointcut的matches判断过程中,会用到transactionAttributeSource对象,这个transactionAttributeSource对象是在对TransactionInterceptor进行依赖注入时就配置好的。它的设置是在TransactionInterceptor的基类TransactionAspectSupport中完成的,配置的是一个NameMatchTransactionAttributeSource对象。

org.springframework.transaction.interceptor.TransactionAspectSupport#setTransactionAttributes的代码实现如下:

ini 复制代码
// 这里新建一个NameMatchTransactionAttributeSource对象,同时也把IOC容器中设置的事务处理属性配置到这个NameMatchTransactionAttributeSource中
public void setTransactionAttributes(Properties transactionAttributes) {
    NameMatchTransactionAttributeSource tas = new NameMatchTransactionAttributeSource();
    tas.setProperties(transactionAttributes);
    this.transactionAttributeSource = tas;
}

在以上的代码实现中,可以看到,NameMatchTransactionAttributeSource作为TransactionAttributeSource的具体实现,是实际完成事务处理属性读入和匹配的地方。对于NameMatchTransactionAttributeSource是怎样实现事务处理属性的读入和匹配的,可以在如下代码清单中看到。在对事务属性TransactionAttributes进行设置时,会从事务处理属性配置中读取事务方法名和配置属性,在得到配置的事务方法名和属性以后,会把它们作为键值对加人到个nameMap中。 在应用调用目标方法的时候,因为这个目标方法已经被TransactionProxyFactoryBean代理,所以TransactionProxyFactoryBean需要判断这个调用方法是否是事务方法。这个判断的实现,是通过在NameMatchTransactionAttributeSource中能否为这个调用方法返回事务属性来完成的。具体的实现过程是这样的:首先,以调用方法名为索引在nameMap中查找相应的事务处理属性值,如果能够找到,那么就说明该调用方法和事务方法是直接对应的,如果找不到,那么就会遍历整个nameMap,对保存在nameMap中的每一个方法名,使用PatternMatchUtils的SimpleMatch方法进行命名模式上的匹配。这里使用PatternMatchUtils进行匹配的原因是,在设置事务方法的时候,可以不需要为事务方法设置一个完整的方法名而可以通过设置方法名的命名模式来完成,比如可以通过对通配符*的使用等。所以,如果直接通过方法名没能够匹配上,而通过方法名的命名模式能够匹配上,这个方法也是需要进行事务处理的方法,相对应地,它所配置的事务处理属性也会从nameMap中取出来,从而触发事务处理拦截器的拦截。

org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource类的实现如下:

typescript 复制代码
public class NameMatchTransactionAttributeSource
       implements TransactionAttributeSource, EmbeddedValueResolverAware, InitializingBean, Serializable {

    protected static final Log logger = LogFactory.getLog(NameMatchTransactionAttributeSource.class);

    /** Keys are method names; values are TransactionAttributes. */
    private final Map<String, TransactionAttribute> nameMap = new HashMap<>();

    @Nullable
    private StringValueResolver embeddedValueResolver;

    public void setNameMap(Map<String, TransactionAttribute> nameMap) {
       nameMap.forEach(this::addTransactionalMethod);
    }
    // 设置配置的事务方法,transactionAttributes对应xml文件中配置的值,示例:* -> PROPAGATION_REQUIRED
    public void setProperties(Properties transactionAttributes) {
       // 新建TransactionAttributeEditor
       TransactionAttributeEditor tae = new TransactionAttributeEditor();
       Enumeration<?> propNames = transactionAttributes.propertyNames();
       while (propNames.hasMoreElements()) {
          String methodName = (String) propNames.nextElement();
          String value = transactionAttributes.getProperty(methodName);
          tae.setAsText(value);
          TransactionAttribute attr = (TransactionAttribute) tae.getValue();
          addTransactionalMethod(methodName, attr);
       }
    }
    // 将对应的包含事务属性的方法加入nameMap中
    public void addTransactionalMethod(String methodName, TransactionAttribute attr) {
       if (logger.isDebugEnabled()) {
          logger.debug("Adding transactional method [" + methodName + "] with attribute [" + attr + "]");
       }
       if (this.embeddedValueResolver != null && attr instanceof DefaultTransactionAttribute) {
          ((DefaultTransactionAttribute) attr).resolveAttributeStrings(this.embeddedValueResolver);
       }
       this.nameMap.put(methodName, attr);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
       this.embeddedValueResolver = resolver;
    }

    @Override
    public void afterPropertiesSet()  {
       for (TransactionAttribute attr : this.nameMap.values()) {
          if (attr instanceof DefaultTransactionAttribute) {
             ((DefaultTransactionAttribute) attr).resolveAttributeStrings(this.embeddedValueResolver);
          }
       }
    }
    // 对调用的方法进行判断,判断它是否是事务方法,如果是事务方法,那么取出相应的事务配置属性
    @Override
    @Nullable
    public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
       if (!ClassUtils.isUserLevelMethod(method)) {
          return null;
       }

       // 判断当前目标调用的方法与配置的事务方法是否直接匹配
       String methodName = method.getName();
       TransactionAttribute attr = this.nameMap.get(methodName);
       // 如果不能直接匹配,就通过调用PatternMatchUtils的simpleMatch方法来进行匹配判断
       if (attr == null) {
          // Look for most specific name match.
          String bestNameMatch = null;
          for (String mappedName : this.nameMap.keySet()) {
             if (isMatch(methodName, mappedName) &&
                   (bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
                attr = this.nameMap.get(mappedName);
                bestNameMatch = mappedName;
             }
          }
       }

       return attr;
    }

    // 事务方法的匹配判断,具体的实现在PatternMatchUtils中实现
    protected boolean isMatch(String methodName, String mappedName) {
       return PatternMatchUtils.simpleMatch(mappedName, methodName);
    }


    @Override
    public boolean equals(@Nullable Object other) {
       if (this == other) {
          return true;
       }
       if (!(other instanceof NameMatchTransactionAttributeSource)) {
          return false;
       }
       NameMatchTransactionAttributeSource otherTas = (NameMatchTransactionAttributeSource) other;
       return ObjectUtils.nullSafeEquals(this.nameMap, otherTas.nameMap);
    }

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

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

}

getTransactionAttribute的典型调用过程如下:

vbnet 复制代码
isMatch:161, NameMatchTransactionAttributeSource (org.springframework.transaction.interceptor) // 方法的入参为insert和*
getTransactionAttribute:140, NameMatchTransactionAttributeSource (org.springframework.transaction.interceptor) // 方法的入参为public abstract void com.spring.tx.NewsDao.insert(java.lang.String,java.lang.String)和class com.spring.tx.NewsDaoImpl
matches:47, TransactionAttributeSourcePointcut (org.springframework.transaction.interceptor)
getInterceptorsAndDynamicInterceptionAdvice:76, DefaultAdvisorChainFactory (org.springframework.aop.framework)
getInterceptorsAndDynamicInterceptionAdvice:470, AdvisedSupport (org.springframework.aop.framework)
invoke:225, JdkDynamicAopProxy (org.springframework.aop.framework)
insert:-1, $Proxy21 (com.sun.proxy)
main:24, SpringTest (com.spring.tx)

通过以上过程可以得到与目标对象调用方法相关的TransactionAttribute对象,在这个对象中,封装了事务处理的配置。具体来说,在前面的匹配过程中,如果匹配返回的结果是null,那么说明当前的调用方法不是一个事务方法,不需要纳入Spring统一的事务管理中,因为它并没有配置在TransactionProxyFactoryBean的事务处理设置中。如果返回的TransactionAttribute对象不是null,那么这个返回的TransactionAttribute对象就已经包含了对事务方法的配置信息,对应这个事务方法的具体事务配置也已经读入到TransactionAttribute对象中了,为Transactionlnterceptor做好了对调用的目标方法添加事务处理的准备。

3、事务处理拦截器的设计与实现

在完成以上的准备工作以后,经过TransactionProxyFactoryBean的AOP包装,此时如果对目标对象进行方法调用,起作用的对象实际上是一个Proxy代理对象,对目标对象方法的调用,不会直接作用在TransactionProxyFactoryBean设置的目标对象上,而会被设置的事务处理拦截器拦截。而在TransactionProxyFactoryBean的AOP实现中,获取Proxy对象的过程并不复杂,TransactionProxyFactoryBean作为一个FactoryBean,对这个Bean的对象的引用是通过调用TransactionProxyFactoryBean的getObject方法来得到的。这个方法大家已经很熟悉了,如下代码清单所示。

org.springframework.aop.framework.AbstractSingletonProxyFactoryBean#getObject的实现如下:

typescript 复制代码
// 返回的是一个Proxy, 这个Proxy是ProxyFactory生成的代理对象,已经封装了对事务处理的拦截器配置
public Object getObject() {
    if (this.proxy == null) {
       throw new FactoryBeanNotInitializedException();
    }
    // this.proxy已经在org.springframework.aop.framework.AbstractSingletonProxyFactoryBean#afterPropertiesSet中使用proxyFactory.getProxy(this.proxyClassLoader)进行了初始化
    return this.proxy;
}

关于如何对AOP代理起作用,如果还有印象,大家会注意到一个重要的invoke方法,这个invoke方法是Proxy代理对象的回调方法,在调用Proxy对象的代理方法时触发这个回调。在事务处理拦截器TransactionInterceptor中,invoke方法的实现如下代码清单所示。可以看到,这个回调的实现是很清晰的,其过程是,首先获得调用方法的事务处理配置,这个取得事务处理配置的过程已经在前面分析过了,在得到事务处理配置以后,会取得配置的PlatformTransactionManager,由这个事务处理器来实现事务的创建、提交、回滚操作。

PlatformTransactionManager事务处理器是在IoC容器中配置的,比如,大家已经很熟悉的DataSourceTransactionManager和HibernateTransactionManager。有了这一系列的具体事务处理器的配置,在Spring事务处理模块的统一管理下:由这些具体的事务处理器来完成事务的创建、提交、回滚等底层的事务操作。

org.springframework.transaction.interceptor.TransactionInterceptor#invoke的方法实现如下:

typescript 复制代码
public Object invoke(MethodInvocation invocation) throws Throwable {
    // Work out the target class: may be {@code null}.
    // The TransactionAttributeSource should be passed the target class
    // as well as the method, which may be from an interface.
    // 得到代理的目标对象,并将事务属性传递给目标对象
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);

    // Adapt to TransactionAspectSupport's invokeWithinTransaction...
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() {
       @Override
       @Nullable
       public Object proceedWithInvocation() throws Throwable {
          return invocation.proceed();
       }
       @Override
       public Object getTarget() {
          return invocation.getThis();
       }
       @Override
       public Object[] getArguments() {
          return invocation.getArguments();
       }
    });
}

调用的父类的org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction方法的实现如下:

scss 复制代码
// targetClass为需要代理的目标对象
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
       final InvocationCallback invocation) throws Throwable {

    // If the transaction attribute is null, the method is non-transactional. 获取事务的属性配置,通过TransactionAttributeSource对象取得
    TransactionAttributeSource tas = getTransactionAttributeSource();
    final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
    // 根据TransactionProxyFactoryBean的配置信息获得具体的事务处理器
    final TransactionManager tm = determineTransactionManager(txAttr);
    // 响应式事务管理逻辑
    if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
       boolean isSuspendingFunction = KotlinDetector.isSuspendingFunction(method);
       boolean hasSuspendingFlowReturnType = isSuspendingFunction &&
             COROUTINES_FLOW_CLASS_NAME.equals(new MethodParameter(method, -1).getParameterType().getName());
       if (isSuspendingFunction && !(invocation instanceof CoroutinesInvocationCallback)) {
          throw new IllegalStateException("Coroutines invocation not supported: " + method);
       }
       CoroutinesInvocationCallback corInv = (isSuspendingFunction ? (CoroutinesInvocationCallback) invocation : null);

       ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
          Class<?> reactiveType =
                (isSuspendingFunction ? (hasSuspendingFlowReturnType ? Flux.class : Mono.class) : method.getReturnType());
          ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(reactiveType);
          if (adapter == null) {
             throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
                   method.getReturnType());
          }
          return new ReactiveTransactionSupport(adapter);
       });

       InvocationCallback callback = invocation;
       if (corInv != null) {
          callback = () -> CoroutinesUtils.invokeSuspendingFunction(method, corInv.getTarget(), corInv.getArguments());
       }
       Object result = txSupport.invokeWithinTransaction(method, targetClass, callback, txAttr, (ReactiveTransactionManager) tm);
       if (corInv != null) {
          Publisher<?> pr = (Publisher<?>) result;
          return (hasSuspendingFlowReturnType ? KotlinDelegate.asFlow(pr) :
                KotlinDelegate.awaitSingleOrNull(pr, corInv.getContinuation()));
       }
       return result;
    }

    PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    // 这里区分不同类型的PlatformTransactionManager,因为他们的调用方式不同,对Callback**Manager来说,需要回调函数来实现事务的创建和提交,对非Callback**Manager来说,不需要通过回调函数来实现事务的创建和提交,DataSourceTransactionManager就不是Callback**Manager,不需要通过回调的方式来使用
    if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
       // 创建事务,同时把创建事务过程中得到的信息放到TransactionInfo中去,TransactionInfo是保存当前事务状态的对象
       // Standard transaction demarcation with getTransaction and commit/rollback calls.
       TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

       Object retVal;
       try {
          // This is an around advice: Invoke the next interceptor in the chain.
          // This will normally result in a target object being invoked.
          // 这里的调用使处理沿着拦截器链进行,使最后目标对象的方法得到调用
          retVal = invocation.proceedWithInvocation();
       }
       catch (Throwable ex) {
          // 如果在事务处理方法调用中出现了异常,事务处理如何进行需要根据具体的情况考虑回滚或者提交
          completeTransactionAfterThrowing(txInfo, ex);
          throw ex;
       }
       finally {
          // 把与线程绑定的TransactionInfo设置为oldTransactionInfo
          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;
    }

    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) {
                // 通过txAttr.rollbackOn()方法判断是否需要回滚
                if (txAttr.rollbackOn(ex)) {
                   // RuntimeException会导致事务回滚
                   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;
    }
}

以事务提交为例,通过下图所示的时序图来简要的说明这个过程。在调用代理的事务方法时,因为前面已经完成了一系列AOP配置,对事务方法的调用,最终启动TransactionInterceptor拦截器的invoke方法。在这个方法中,首先会读取该事务方法的事务属性配置,然后根据事务属性配置以及具体事务处理器的配置来决定采用哪一个事务处理器这个事务处理器实际上是一个PlatformTransactionManager。在确定好具体的事务处理器之后会根据事务的运行情况和事务配置来决定是不是需要创建新的事务。对于Spring而言,事务的管理实际上是通过一个TransactionInfo对象来完成的,在该对象中,封装了事务对象和事务处理的状态信息,这是事务处理的抽象。在这一步完成以后,会对拦截器链进行处理,因为有可能在该事务对象中还配置了除事务处理AOP之外的其他挡截器。在结束对挡截器链处理之后,会对Transactioninfo中的信息进行更新,以反映最近的事务处理情况,在这个时候,也就完成了事务提交的准备,通过调用事务处理器PlatformTransactionManager的commitTransactionAfterReturning方法来完成事务的提交。这个提交的处理过程已经封装在PlatformTransactionManager的事务处理器中了,而与具体数据源相关的处理过程,最终委托给相关的具体事务处理器来完成,比如DataSourceTransactionManager、HibernateTransactionManager等。

在这个invoke()方法的实现中,可以看到整个事务处理在AOP拦截器中实现的全过程。同时,它也是Spring采用AOP封装事务处理和实现声明式事务处理的核心部分。这部分实现,是一个桥梁,它胶合了具体的事务处理和SpringAOP框架,可以看成是一个SpringAOP应用,在这个桥梁搭建完成以后,Spring事务处理的实现就开始了。

Spring事务处理的设计与实现

Spring事务处理的编程式使用

声明式事务通过XML配置的方式进行事务的配置,编程式事务通过编码的方式在业务代码中使用事务,提供更灵活的细节控制。

声明式事务处理的即开即用特性为用户提供了很大的方便。与前面介绍的对IoC容器的使用相类似,Spring的事务处理也可以通过编程的方式进行使用,了解这种使用方式,对理解Spring事务处理的实现是有很大帮助的。对于Spring事务处理的编程式使用如下代码清单所示。

ini 复制代码
TransactionDefinition td = new DefaultTransactionDefinition();
PlatformTransactionManager transactionManager = new DataSourceTransactionManager();
TransactionStatus status = transactionManager.getTransaction(td);
try {
    // 需要进行事务处理的方法调用
} catch (Exception e) {
    transactionManager.rollback(status);
    throw e;
}
transactionManager.commit(status);

在编程式使用事务处理的过程中,利用DefaultTransactionDefinition对象来持有事务处理属性。同时,在创建事务的过程中得到一个TransactionsStatus对象,然后通过直接调用transactionManager的commit()和rollback()方法来完成事务处理。在这个编程式使用事务管理的过程中,没有看到框架特性的使用,非常简单和直接,很好地说明了事务管理的基本实现过程以及在Spring事务处理实现中涉及一些主要的类,比如TransationStatus、TransactionManager等对这些类的使用与声明式事务处理的最终实现是一样的。 与编程式使用事务管理不同,在使用声明式事务处理的时候,因为涉及Spring框架对事务处理的统一管理,以及对并发事务和事务属性的处理,所以采用的是一个比较复杂的处理过程,但复杂归复杂,这个过程对使用声明式事务处理的应用来说,基本上是不可见的,而是由Spring框架来完成的。有了这些背景铺垫和前面对AOP封装事务处理的了解,下面来看看Spring是如何提供声明式事务处理的,Spring在这个相对较为复杂的过程中封装了什么,这层封装包括在事务处理中事务的创建、提交和回滚等比较核心的操作。下面对相关内容进行详细分析。

事务的创建

作为声明式事务处理实现的起始点,需要注意Transactionlnterceptor拦截器的invoke回调中使用的createTransactionIfNecessary方法,这个方法是在TransactionInterceptor的基类TransactionAspectSupport中实现的。为了了解这个方法的实现,先分析一下TransactionInterceptor的基类实现TransactionAspectSupport,并以这个方法的实现为入口,了解Spring是如何根据当前的事务状态和事务属性配置完成事务创建的。这个TransactionAspectSupport的createTransactionIfNecessary方法作为事务创建的入口,其具体的实现时序如下图所示。在createTransactionIfNecessary方法的调用中,会向AbstractTransactionManager执行getTransaction(),这个获取Transaction事务对象的过程,在AbstractTransactionManager实现中需要对事务的情况做出不同的处理,然后,创建一个TransactionStatus,开把这个TransactionStatus设置到对应的Transactionlnfo中去,同时将Transactionlnfo和当前的线程绑定,从而完成事务的创建过程。如果从源代码实现的角度上去了解这个过程,那么可以参考如下代码清单所示的代码。在代码清单的createTransactionIfNeccessary方法调用中,可以看到两个重要的数据对象TransactionStatus和TransactionInfo的创建,这两个对象持有的数据是事务处理器对事务进行处理的主要依据,对这两个对象的便用穿看整个事务处理的全过程。

org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary的实现如下:

less 复制代码
// TransactionAttribute为事务的配置属性,PlatformTransactionManager为事务管理器,joinpointIdentification为方法的名字
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
       @Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

    // If no name specified, apply method identification as transaction name.
    // 如果没有指定名字,使用方法特征作为事务名
    if (txAttr != null && txAttr.getName() == null) {
       txAttr = new DelegatingTransactionAttribute(txAttr) {
          @Override
          public String getName() {
             return joinpointIdentification;
          }
       };
    }
    // 这个TransactionStatus封装了事务执行的状态信息
    TransactionStatus status = null;
    if (txAttr != null) {
       if (tm != null) {
          // 使用定义好的事务方法的配置信息,事务创建由事务处理器来完成,同时返回TransactionStatus来记录当前的事务状态,包括已经创建的事务
          status = tm.getTransaction(txAttr);
       }
       else {
          if (logger.isDebugEnabled()) {
             logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
                   "] because no transaction manager has been configured");
          }
       }
    }
    // 准备TransactionInfo,TransactionInfo对象封装了事务处理的配置信息以及TransactionStatus
    return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
       @Nullable TransactionAttribute txAttr, String joinpointIdentification,
       @Nullable TransactionStatus status) {

    TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
    if (txAttr != null) {
       // We need a transaction for this method...
       if (logger.isTraceEnabled()) {
          logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
       }
       // The transaction manager will flag an error if an incompatible tx already exists.
       // 这里为TransactionInfo设置TransactionStatus, TransactionStatus非常重要,它持有管理事务处理需要的数据,比如,transaction对象就是由TransactionStatus来持有的
       txInfo.newTransactionStatus(status);
    }
    else {
       // The TransactionInfo.hasTransaction() method will return false. We created it only
       // to preserve the integrity of the ThreadLocal stack maintained in this class.
       if (logger.isTraceEnabled()) {
          logger.trace("No need to create transaction for [" + joinpointIdentification +
                "]: This method is not transactional.");
       }
    }

    // We always bind the TransactionInfo to the thread, even if we didn't create
    // a new transaction here. This guarantees that the TransactionInfo stack
    // will be managed correctly even if no transaction was created by this aspect.
    // 这里把当前的TransactionInfo与线程绑定,同时在TransactionInfo中由一个变量来保存以前的TransactionInfo,这样就持有了一连串与事务处理相关的TransactionInfo,虽然不一定创建新的事务,但是总会在请求事务时创建TransactionInfo
    txInfo.bindToThread();
    return txInfo;
}

在以上的处理过程之后,可以看到,具体的事务创建可以交给事务处理器来完成。在事务的创建过程中,已经为事务的管理做好了准备,包括记录事务处理状态,以及绑定事务信息和线程等。下面到事务处理器中去了解一下更底层的事务创建过程。createTransactionifNecessary()方法被如下代码清单中的tm.getTransactiontxAttr()调用触发,生成一个TransactionStatus对象,封装了底层事务对象的创建。可以看到,AbstractPlatformTransactionManager提供了创建事务的模板,这个模板会被具体的事务处理器所使用,如代码清单所示。在代码清单中可以看到,AbstractPlatformTransactionManager会根据事务属性配置和当前进程绑定的事务信息,对事务是否需要创建,怎样创建进行一些通用的处理,然后把事务创建的底层工作交给具体的事 务处理器完成。尽管具体的事务处理器完成事务创建的过程各不相同,但是不同的事务处理器对事务属性和当前进程事务信息的处理都是相同的,这些相同的处理部分就是在代码清单中看到的,在AbstractPlatformTransactionManager的实现中完成的,这个实现过程是Spring提供统一事务处理的一个重要部分。

org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction的实现如下:

java 复制代码
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
       throws TransactionException {

    // Use defaults if no transaction definition given.
    TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
    // 这个doGetTransaction()是抽象函数,Transaction对象的取得由具体的事务处理器实现,比如DataSourceTransactionManager
    Object transaction = doGetTransaction();
    boolean debugEnabled = logger.isDebugEnabled();
    // 检查当前线程是否已经存在事务,如果已经存在事务,那么需要根据在事务属性中定义的事务传播属性配置来处理事务的产生
    if (isExistingTransaction(transaction)) {
       // 这块对当前线程中已经有事务存在的情况进行处理,结果封装在TransactionStatus中
       return handleExistingTransaction(def, transaction, debugEnabled);
    }

    // Check definition settings for new transaction.
    if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
       throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
    }

    // 当前没有事务存在,这时需要根据事务属性设置来创建事务,这里会看到对事务传播属性设置的处理,比如mandatory, required, required_new, nested等,这里的处理对理解这些属性的使用是非常有帮助的
    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) {
       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) {
          resume(null, suspendedResources);
          throw ex;
       }
    }
    else {
       // Create "empty" transaction: no actual transaction, but potentially synchronization.
       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);
       return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
    }
}


private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
       boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {

    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    DefaultTransactionStatus status = newTransactionStatus(
          definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
    // 这里是创建事务的调用,由具体的事务处理器完成,比如DataSourceTransactionManager等
    doBegin(transaction, definition);
    prepareSynchronization(status, definition);
    return status;
}

从以上代码清单中可以看到AbstractTransactionManager提供的创建事务的实现模板,在这个模板的基础上,具体的事务处理器需要定义自已的实现来完成底层的事务创建工作,比如需要实现isExistingTransaction和doBegin方法。关于这些由具体事务处理器实现的方法会在下面结合具体的事务处理器实现(比如DataSourceTransactionManager和HibernateTransactionManager)进行分析。 事务创建的结果是生成一个TransactionStatus对象,通过这个对象来保存事务处理需要的基本信息,这个对象与前面提到过的TransactionInfo对象联系在一起,TransactionStatus是TransactionInfo的一个属性,然后会把TransactionInfo保存在ThreadLocal对象里,这样当前线程可以通过ThreadLocal对象取得Transactionlnfo,以及与这个事务对应的TransactionStatus对象,从而把事务的处理信息与调用事务方法的当前线程绑定起来。在AbstractPlatformTransactionManager创建事务的过程中,可以看到TransactionStatus的创建过程,如下代码清单所示。

org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareSynchronization的实现如下:

scss 复制代码
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
    // 这里判断是不是新事务,如果是新事务,那么需要把事务属性存放在当前线程中,TransactionSynchronizationManager维护一系列的ThreadLocal变量来维持事务属性,比如并发事务隔离级别,是否有活跃的事务等
    if (status.isNewSynchronization()) {
       TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
       TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
             definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
                   definition.getIsolationLevel() : null);
       TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
       TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
       TransactionSynchronizationManager.initSynchronization();
    }
}

新事务的创建是比较好理解的,这单需要根据事务属性配置进行创建。所谓创建,首先是把创建工作交给具体的事务处理器来完成,比如DataSourceTransactionManager,把创建的事务对象在TransactionStatus中保存下来,然后将其他的事务属性和线程ThreadLocal变量进行绑定。 相对于创建全新事务的另一种情况是:在创建当前事务时,线程中已经有事务存在了。这种情况同样需要处理,在声明式事务处理中,在当前线程调用事务方法的时候,就会考虑事务的创建处理,这个处理在方法handleExistingTransaction中完成的,如下代码清单所示。这里对现有事务的处理,会涉及事务传播属性的具体处理,比如PROPAGATION_NOT_SUPPORTED,PROPAGATION_REQUIRES_NEW等。

org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction的实现如下:

java 复制代码
private TransactionStatus handleExistingTransaction(
       TransactionDefinition definition, Object transaction, boolean debugEnabled)
       throws TransactionException {
    // 如果当前线程已有事务存在,并且事务传播属性设置为never,那么抛出异常,说明这种情况是有问题的,Spring无法处理当前的事务创建
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
       throw new IllegalTransactionStateException(
             "Existing transaction found for transaction marked with propagation 'never'");
    }
    // 如果当前事务的配置属性是PROPAGATION_NOT_SUPPORTED,同时当前线程已经存在事务了,那么将事务挂起
    if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
       if (debugEnabled) {
          logger.debug("Suspending current transaction");
       }
       Object suspendedResources = suspend(transaction);
       boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
       // 注意这里的参数,transaction为null,newTransaction为false,意味着事务方法不需要放在事务环境中执行,同时挂起事务的信息记录也保存在TransactionStatus中,这里包括了进程ThreadLocal对事务信息的记录
       return prepareTransactionStatus(
             definition, null, false, newSynchronization, debugEnabled, suspendedResources);
    }
    // 如果当前事务的配置属性是PROPAGATION_REQUIRES_NEW,创建新事务,同时把当前线程中存在的事务挂起,此处与创建全薪事务的区别是,需要考虑已有事务的挂起处理
    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 {
          return startTransaction(definition, transaction, debugEnabled, suspendedResources);
       }
       catch (RuntimeException | Error beginEx) {
          resumeAfterBeginException(transaction, suspendedResources, beginEx);
          throw beginEx;
       }
    }
    // 嵌套事务的创建
    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()) {
          // Create savepoint within existing Spring-managed transaction,
          // through the SavepointManager API implemented by TransactionStatus.
          // Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
          // 在Spring管理的事务中,创建事务保存点
          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.
          return startTransaction(definition, transaction, debugEnabled, null);
       }
    }

    // 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");
          }
       }
    }
    // 返回TransactionStatus,注意第三个参数false代表当前事务方法没有使用新的事务
    boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
    return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}

事务的挂起

事务的挂起牵涉线程与事务处理信息的保存,可以看一下事务挂起的实现,如下代码所示。

org.springframework.transaction.support.AbstractPlatformTransactionManager#suspend的实现如下:

java 复制代码
// 返回的SuspendResourcesHolder会作为参数传给TransactionStatus
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
    if (TransactionSynchronizationManager.isSynchronizationActive()) {
       List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
       try {
          Object suspendedResources = null;
          // 把挂起事务的处理交给具体事务处理器去完成,如果具体的事务处理器不支持事务挂起,那么默认抛出异常
          if (transaction != null) {
             suspendedResources = doSuspend(transaction);
          }
          // 这里在线程中保存与事务处理有关的信息,并重置线程中相关的ThreadLocal变量
          String name = TransactionSynchronizationManager.getCurrentTransactionName();
          TransactionSynchronizationManager.setCurrentTransactionName(null);
          boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
          TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
          Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
          TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
          boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
          TransactionSynchronizationManager.setActualTransactionActive(false);
          return new SuspendedResourcesHolder(
                suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
       }
       catch (RuntimeException | Error ex) {
          // doSuspend failed - original transaction is still active...
          doResumeSynchronization(suspendedSynchronizations);
          throw ex;
       }
    }
    else if (transaction != null) {
       // Transaction active but no synchronization active.
       Object suspendedResources = doSuspend(transaction);
       return new SuspendedResourcesHolder(suspendedResources);
    }
    else {
       // Neither transaction nor synchronization active.
       return null;
    }
}

基于以上内容,就可以完成声明式事务处理的创建了。

事务的提交

下面来看看事务提交是如何实现的。有了前面的对事务创建的分析,下面来分析一下在Spring中,声明式事务处理的事务提交是如何完成的。事务提交的入口调用在TransactionInteceptor的invoke方法中实现,如以下的代码片段所示:

scss 复制代码
commitTransactionAfterReturning(txInfo);

在这个调用中,我们看到的txInfo是TransactionInfo对象,这个参数TransactionInfo对象是创建事务时生成的。同时,Spring的事务管理框架生成的TransactionStatus对象就包含在TransactionInfo对象中。这个commitTransactionAfterReturning方法在TransactionInteceptor的实现部分是比较简单的,它通过直接调用事务处理器来完成事务提交,如下代码清单所示。

org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning的实现如下:

less 复制代码
protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
    if (txInfo != null && txInfo.getTransactionStatus() != null) {
       if (logger.isTraceEnabled()) {
          logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
       }
       txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
    }
}

与前面分析事务的创建过程一样,我们需要到事务处理器中去看看事务是如何提交的。同样,在AbstractPlatformTransactionManager中也有一个模板方法支持具体的事务处理器对事务提交的实现,在AbstractPlatformTransactionManager中,这个模板方法的实现与前面我们看到的getTransaction很类似,如下代码清单所示。

scss 复制代码
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;
    }

    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;
    }

    processCommit(defStatus);
}

private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
       boolean beforeCompletionInvoked = false;

       try {
          boolean unexpectedRollback = false;
          // 事务提交的准备工作由具体的事务处理器完成
          prepareForCommit(status);
          triggerBeforeCommit(status);
          triggerBeforeCompletion(status);
          beforeCompletionInvoked = true;

          if (status.hasSavepoint()) {
             if (status.isDebug()) {
                logger.debug("Releasing transaction savepoint");
             }
             unexpectedRollback = status.isGlobalRollbackOnly();
             status.releaseHeldSavepoint();
          }
          // 对当前线程中保存的事务状态进行处理,如果当前事务是一个新事务,调用具体事务处理器完成提交,如果当前所持有的事务不是一个新事务,则不提交,由已经存在的事务来完成提交,doCommit为abstract方法
          else if (status.isNewTransaction()) {
             if (status.isDebug()) {
                logger.debug("Initiating transaction commit");
             }
             unexpectedRollback = status.isGlobalRollbackOnly();
             doCommit(status);
          }
          else if (isFailEarlyOnGlobalRollbackOnly()) {
             unexpectedRollback = status.isGlobalRollbackOnly();
          }

          // Throw UnexpectedRollbackException if we have a global rollback-only
          // marker but still didn't get a corresponding exception from commit.
          if (unexpectedRollback) {
             throw new UnexpectedRollbackException(
                   "Transaction silently rolled back because it has been marked as rollback-only");
          }
       }
       catch (UnexpectedRollbackException ex) {
          // can only be caused by doCommit
          triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
          throw ex;
       }
       catch (TransactionException ex) {
          // can only be caused by doCommit
          if (isRollbackOnCommitFailure()) {
             doRollbackOnCommitException(status, ex);
          }
          else {
             triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
          }
          throw ex;
       }
       catch (RuntimeException | Error ex) {
          if (!beforeCompletionInvoked) {
             triggerBeforeCompletion(status);
          }
          doRollbackOnCommitException(status, ex);
          throw ex;
       }

       // Trigger afterCommit callbacks, with an exception thrown there
       // propagated to callers but the transaction still considered as committed.
       try {
          // 触发afterCommit()回滚
          triggerAfterCommit(status);
       }
       finally {
          triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
       }

    }
    finally {
       cleanupAfterCompletion(status);
    }
}

可以看到,事务提交的准备都是由具体的事务处理器来实现的。当然,对这些事务提交的处理,需要通过对TransactionStatus保存的事务处理的相关状态进行判断。提交过程涉及AbstractPlatformTransactionManager中的doCommit和prepareForCommit方法,它们都是抽象方法,都在具体的事务处理器中完成实现,在下面对具体事务处理器的实现原理的分析中可以看到对这些实现方法的具体分析。

事务的回滚

事务回滚的处理。

org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback的实现如下:

java 复制代码
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
    try {
       boolean unexpectedRollback = unexpected;

       try {
          triggerBeforeCompletion(status);
          // 嵌套事务的回滚处理
          if (status.hasSavepoint()) {
             if (status.isDebug()) {
                logger.debug("Rolling back transaction to savepoint");
             }
             status.rollbackToHeldSavepoint();
          }// 新建事务的回滚处理
          else if (status.isNewTransaction()) {
             if (status.isDebug()) {
                logger.debug("Initiating transaction rollback");
             }
             doRollback(status);
          }
          else {
             // Participating in larger transaction 没有新建事务的回滚处理
             if (status.hasTransaction()) {
                if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
                   if (status.isDebug()) {
                      logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
                   }
                   doSetRollbackOnly(status);
                }
                else { // 由线程中的前一个事务来处理回滚,这里不执行任何操作
                   if (status.isDebug()) {
                      logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
                   }
                }
             }
             else {
                logger.debug("Should roll back transaction but cannot - no transaction available");
             }
             // Unexpected rollback only matters here if we're asked to fail early
             if (!isFailEarlyOnGlobalRollbackOnly()) {
                unexpectedRollback = false;
             }
          }
       }
       catch (RuntimeException | Error ex) {
          triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
          throw ex;
       }

       triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);

       // Raise UnexpectedRollbackException if we had a global rollback-only marker
       if (unexpectedRollback) {
          throw new UnexpectedRollbackException(
                "Transaction rolled back because it has been marked as rollback-only");
       }
    }
    finally {
       cleanupAfterCompletion(status);
    }
}
相关推荐
美美的海顿12 分钟前
springboot基于Java的校园导航微信小程序的设计与实现
java·数据库·spring boot·后端·spring·微信小程序·毕业设计
一只淡水鱼662 小时前
【mybatis】基本操作:详解Spring通过注解和XML的方式来操作mybatis
java·数据库·spring·mybatis
Q_19284999064 小时前
基于Springcloud的智能社区服务系统
后端·spring·spring cloud
Ch.yang6 小时前
【Spring】 Bean 注入 HttpServletRequest 能保证线程安全的原理
java·spring·代理模式
昙鱼7 小时前
springboot创建web项目
java·前端·spring boot·后端·spring·maven
爱学习的白杨树7 小时前
MyBatis的一级、二级缓存
java·开发语言·spring
中草药z7 小时前
【Spring】深入解析 Spring 原理:Bean 的多方面剖析(源码阅读)
java·数据库·spring boot·spring·bean·源码阅读
m0_748256787 小时前
SpringBoot 依赖之Spring Web
前端·spring boot·spring
组合缺一7 小时前
Solon v3.0.5 发布!(Spring 可以退休了吗?)
java·后端·spring·solon
栗豆包8 小时前
w118共享汽车管理系统
java·spring boot·后端·spring·tomcat·maven