上一篇文章分析了@EnableTransactionManagement注解的3个方法,比较简单。

今天开始分析@EnableTransactionManagement的相对复杂的部分,就是他Import进来的配置类。

通过@EnableTransactionManagement注解的源码,我们知道他Import了:TransactionManagementConfigurationSelector这个配置类。

TransactionManagementConfigurationSelector

这是个配置选择器,selectImports方法中判断我们上一篇文章分析过的EnableTransactionManagement的adviceMode,在PROXY模式下返回两个类:

  1. AutoProxyRegistrar
  2. ProxyTransactionManagementConfiguration

    protected String[] selectImports(AdviceMode adviceMode) {
         switch (adviceMode) {
             case PROXY:
                 return new String[] {AutoProxyRegistrar.class.getName(),
                         ProxyTransactionManagementConfiguration.class.getName()};
             case ASPECTJ:
                 return new String[] {determineTransactionAspectClass()};
             default:
                 return null;
         }
     }

    ProxyTransactionManagementConfiguration

    @Configuration class that registers the Spring infrastructure beans necessary to enable proxy-based annotation-driven transaction management.
    Since:
    3.1
    See Also:
    EnableTransactionManagement, TransactionManagementConfigurationSelector
    Author:
    Chris Beams, Sebastien Deleuze
    注册Spring基础bean以启用proxy模式下的注解驱动的事务管理

这是一个用来向Spring容器注册通过注解方式启用事务管理的基础bean的配置类。

共向Spring容器注册了3个Bean:

  1. TransactionAttributeSource
  2. BeanFactoryTransactionAttributeSourceAdvisor
  3. TransactionInterceptor

TransactionAttributeSource

我们在Spring事务框架中分析过,TransactionAttributeSource类持有TransactionAttribute,而TransactionAttribute其实是一个TransactionDefinition,所以,这个Bean是用来持有事务定义的。他直接返回了AnnotationTransactionAttributeSource,我们放在后面再分析。

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
        return new AnnotationTransactionAttributeSource();
    }

BeanFactoryTransactionAttributeSourceAdvisor

创建并返回BeanFactoryTransactionAttributeSourceAdvisor,因为他是AOP中的advisor,所以需要持有advice及pointcut,其中advice就是transactionInterceptor,pointcut在TransactionAttributeSource中:

@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) {
            advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
        }
        return advisor;
    }

TransactionInterceptor

TransactionInterceptor是AOP中拦截器的概念,Bean创建后会持有事务定义TransactoinAttributeSource以及事务管理器TransactionManager。

我们知道AOP拦截器是实现方法增强地方,所以,Spring事务实际上应该就是通过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;
    }

既然transactionInterceptor是AOP中的拦截器,我们直接看看他的invoke方法:
首先,我们所熟悉的,通过参数获取到传入的TargetClass,这一定就是我们的业务类:

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

然后,调用invokeWithinTransaction完成事务处理:

        // 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();
            }
        });
    }

invokeWithinTransaction应该是实现事务控制的关键,篇幅所限,我们下一篇文章专门进行分析。

AnnotationTransactionAttributeSource

Implementation of the org.springframework.transaction.interceptor.TransactionAttributeSource interface for working with transaction metadata in JDK 1.5+ annotation format.
This class reads Spring's JDK 1.5+ Transactional annotation and exposes corresponding transaction attributes to Spring's transaction infrastructure. Also supports JTA 1.2's javax.transaction.Transactional and EJB3's javax.ejb.TransactionAttribute annotation (if present). This class may also serve as base class for a custom TransactionAttributeSource, or get customized through TransactionAnnotationParser strategies.
是TransactionAttributeSource接口的实现类用来与JDK1.5+的事务元数据一起工作。读取JDK1.5+的事务注解并暴露Spring的事务管理机制传递事务属性。...

简单说明一下,不需要逐字逐句翻译JavaDoc,贴出JavaDoc是为了帮助我们分析代码,在分析代码之前对其作用了目的有一个直观的并且是绝对正确的认识,因为JavaDoc不骗人。

读取Transactional注解,而TransactionAttributeSource是持有事务定义的,事务定义是用来持有事务属性的对象,所以我们可以猜测这个这个对象应该会读取@Transactinal注解获取包括隔离级别、传播机制等事务属性并最终存储在事务对象中。

最重要的方法是determineTransactionAttribute,使用注解解析器(SpringTransactionAnnotationParser)解析标注有Transactional注解的方法并获取事务属性生成并返回事务定义。

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element)

BeanFactoryTransactionAttributeSourceAdvisor

Spring框架AOP实现的advisor的类结构:
image.png
BeanFactoryTransactionAttributeSourceAdvisor持有的pointcut其实就是transactionAttributeSource:

private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
        @Override
        @Nullable
        protected TransactionAttributeSource getTransactionAttributeSource() {
            return transactionAttributeSource;
        }
    };

持有的advice是在配置类ProxyTransactionManagementConfiguration中初始化Advisor的时候送进来的transactionInterceptor。

AutoProxyRegistrar

Registers an auto proxy creator against the current BeanDefinitionRegistry as appropriate based on an @Enable* annotation having mode and proxyTargetClass attributes set to the correct values.
Since:
3.1
See Also:
org.springframework.cache.annotation.EnableCaching, org.springframework.transaction.annotation.EnableTransactionManagement
Author:
Chris Beams
依赖于Enable*注解设置正确的mode和proxyTargetClass,注册自动代理创建器。

这个类只有一个方法,正如JavaDoc所说,就是用来注册自动代理生成器的,而且,是在上一节分析过的EnableTransactionManagement注解的proxyTargetClass设置为true、mode设置为Proxy的情况下才会注册。

最终注册的自动代理生成器为:org.springframework.aop.config.internalAutoProxyCreator。

这个被注册到Spring容器的自动代理生成器是用来通过Cglib生成代理对象的。

小结

至此,已经完成了对@EnableTransactionManagement的分析,通过分析我们知道@EnableTransactionManagement向Spring容器注册了自动代理生成器,解析了被@Transactinal注解的类或方法,生成了事务定义TransactionDefinition并注入容器,注入了事务拦截器TransactionInteceptor,看到了拦截器的invoke方法。注入了Advisor,Advisor持有了advice(transactionInterceptor)以及pointCut(TransactionAttributeSource)。

结合AOP概念,已经具备了基于AOP实现事务管理的条件。

下一篇文章分析Spring事务处理拦截器的invokeWithinTransaction方法,应该能够揭开Spring事务控制底层实现的神秘面纱。

上一篇 启用Spring事务管理@EnableTransactionManagement(1)
下一篇 Spring事务控制AOP环绕切入原理


45 声望17 粉丝