4、Spring事务 初始化

万物的起源,AutoConfiuration,这里是TransactionAutoConfiguration,有内部类EnableTransactionManagementConfiguration ,主要作用是引入了注解@EnableTransactionManagement,并确定使用哪种代理方式,jdk或cglib。

@Configuration
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {
 
   @Configuration
    // proxyTargetClass = false,使用jdk代理
   @EnableTransactionManagement(proxyTargetClass = false)
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
    // 使用jdk代理的条件是,需要在yaml文件中手动指定spring.aop.proxy-target-class=false
   public static class JdkDynamicAutoProxyConfiguration {
 
   }
 
   @Configuration
   @EnableTransactionManagement(proxyTargetClass = true)
    // proxyTargetClass = true,使用cglib代理
   @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
    // 使用cglib代理的条件是,需要在yaml文件中手动指定spring.aop.proxy-target-class=true。但是这里matchIfMissing=true,也就是不配置这条属性也会生效
   public static class CglibAutoProxyConfiguration {
 
   }
 
}

看一下注解@EnableTransactionManagement

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
// 重点是这个
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
 
    // true使用cglib代理,false使用jdk代理
   boolean proxyTargetClass() default false;
 
    // 代理模式,使用Spring自带的编译器,或者是aspecj编译器
    // aop和aspectj没有特别大的关系,只是借用了切点、切面的一些概念。aspectj单独有一套对于面向切面编程的实现
   AdviceMode mode() default AdviceMode.PROXY;
 
    // 有多个advisor的时候定义执行顺序
   int order() default Ordered.LOWEST_PRECEDENCE;
 
}

TransactionManagementConfigurationSelector实现了ImportSelector接口,在初始化时会调用selectImports。
这是TransactionManagementConfigurationSelector的类图

image.png
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector {
 
   /**
    * Returns {@link ProxyTransactionManagementConfiguration} or
    * {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
    * and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
    * respectively.
    */
   @Override
   protected String[] selectImports(AdviceMode adviceMode) {
        // 默认是PROXY
      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() {
        // 还没找到javax.transaction.Transactional在哪个包下
      return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
            TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
            TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
   }
 
}

这里selectImports又会向容器中注册AutoProxyRegistrar和ProxyTransactionManagementConfiguration。AutoProxyRegistrar的贡献是向容器中注入了InfrastructureAdvisorAutoProxyCreator,InfrastructureAdvisorAutoProxyCreator是service对象生成代理的关键。

后续过程中发现,其实注册的并不是InfrastructureAdvisorAutoProxyCreator
而是AnnotationAwareAspectJAutoProxyCreator
因为优先级AnnotationAwareAspectJAutoProxyCreator高
但是这并不影响对Spring事务的分析
// AopConfigUtils 优先级列表
private static final List> APC_PRIORITY_LIST = new ArrayList<>(3);

    static {
        // Set up the escalation list...
        // 级别0
        APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
        // 级别1
         APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);      
        // 级别2
        APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
    }

AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar,会调用其registerBeanDefinitions方法

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
   boolean candidateFound = false;
    // 获取CglibAutoProxyConfiguration上的注解,Configuration、EnableTransactionManagement、ConditionalOnProperty
    // 这里需要的是EnableTransactionManagement
   Set annoTypes = importingClassMetadata.getAnnotationTypes();
   for (String annoType : annoTypes) {
        // 获取注解EnableTransactionManagement的属性
      AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
      if (candidate == null) {
         continue;
      }
      Object mode = candidate.get("mode");
      Object proxyTargetClass = candidate.get("proxyTargetClass");
      if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
            Boolean.class == proxyTargetClass.getClass()) {
         candidateFound = true;
            // 如果使用Spring的默认增强模式
         if (mode == AdviceMode.PROXY) {
            // 实际是向容器中注册了bean,InfrastructureAdvisorAutoProxyCreator。具体过程省略了。
            AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
            if ((Boolean) proxyTargetClass) {
                // 给InfrastructureAdvisorAutoProxyCreator的beanDefinition增加属性,proxyTargetClass=true
               AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
               return;
            }
         }
        // 这里没有else了,AdviceMode.ASPECTJ是另外一套实现
      }
   }
   if (!candidateFound && logger.isInfoEnabled()) {
      String name = getClass().getSimpleName();
      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));
   }
}

接着看看,ProxyTransactionManagementConfiguration,里面主要有3个类,

1、BeanFactoryTransactionAttributeSourceAdvisor,定义了切面逻辑TransactionInterceptor和切点TransactionAttributeSourcePointcut(虽然叫切点,但是不是我们常说的切点,只是包含了切点的匹配逻辑)
2、TransactionAttributeSource:包含3个事务注解解析器。SpringTransactionAnnotationParser解析@Transactional,JtaTransactionAnnotationParser解析javax.transaction.Transactional,Ejb3TransactionAnnotationParser解析javax.ejb.TransactionAttribute,
由于我们没有引入jta和ebj相关的jar,所以实际上只有一个解析器:SpringTransactionAnnotationParser
3、TransactionInterceptor:切面逻辑

@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
 
   @Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
      BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
      advisor.setTransactionAttributeSource(transactionAttributeSource());
      advisor.setAdvice(transactionInterceptor());
      if (this.enableTx != null) {
         advisor.setOrder(this.enableTx.getNumber("order"));
      }
      return advisor;
   }
 
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionAttributeSource transactionAttributeSource() {
      return new AnnotationTransactionAttributeSource();
   }
 
   @Bean
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionInterceptor transactionInterceptor() {
      TransactionInterceptor interceptor = new TransactionInterceptor();
      interceptor.setTransactionAttributeSource(transactionAttributeSource());
      if (this.txManager != null) {
         interceptor.setTransactionManager(this.txManager);
      }
      return interceptor;
   }
 
}

这是TransactionAttributeSourcePointcut的类图


image.png
public interface Pointcut {
 
   ClassFilter getClassFilter();
 
   MethodMatcher getMethodMatcher();
 
   Pointcut TRUE = TruePointcut.INSTANCE;
 
}

TransactionAttributeSourcePointcut实现了MethodMatcher接口和PointCut接口。
PointCut由ClassFilter和MethodMatcher构成,并提供一个TruePointcut的实例,当pointCut为TruePointcut时会忽略所有的匹配条件,
ClassFilter和MethodMatcher分别用于在不同的级别上匹配JointPoint,ClassFilter是类级别,MethodMatcher是方法级别。
TransactionAttributeSourcePointcut中重写了方法的匹配规则matches方法
org.springframework.transaction.interceptor.TransactionAttributeSourcePointcut#matches

@Override
public boolean matches(Method method, Class targetClass) {
    // 目标类不能是TransactionalProxy、PlatformTransactionManager、PersistenceExceptionTranslator或其子类
   if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
         PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
         PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
      return false;
   }
    // 返回的是AnnotationTransactionAttributeSource
   TransactionAttributeSource tas = getTransactionAttributeSource();
   return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

getTransactionAttributeSource()是抽象方法,在org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor中对其进行了重写,返回的是在ProxyTransactionManagementConfiguration中定义的AnnotationTransactionAttributeSource。
所以最终决定切点匹配的是AnnotationTransactionAttributeSource中的getTransactionAttribute方法返回值是否为空,为空表示方法不匹配,否则表示匹配,并会生成代理。

AnnotationTransactionAttributeSource继承自AbstractFallbackTransactionAttributeSource,getTransactionAttribute在父类AbstractFallbackTransactionAttributeSource中

org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#getTransactionAttribute

@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class targetClass) {
    // 代理对象是Object,直接返回空
   if (method.getDeclaringClass() == Object.class) {
      return null;
   }
 
   // First, see if we have a cached value.
    // 根据方法和目标类生成缓存Key,判断是否已经缓存过
   Object cacheKey = getCacheKey(method, targetClass);
   TransactionAttribute cached = this.attributeCache.get(cacheKey);
   if (cached != null) {
      // Value will either be canonical value indicating there is no transaction attribute,
      // or an actual transaction attribute.
      if (cached == NULL_TRANSACTION_ATTRIBUTE) {
         return null;
      }
      else {
         return cached;
      }
   }
   else {
        // 具体的获取事务属性的逻辑
      // We need to work it out.
      TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
      // Put it in the cache.
      if (txAttr == null) {
         this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
      }
      else {
         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);
         }
         this.attributeCache.put(cacheKey, txAttr);
      }
      return txAttr;
   }
}

org.springframework.transaction.interceptor.AbstractFallbackTransactionAttributeSource#computeTransactionAttribute

@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) {
   // Don't allow no-public methods as required.
    // publicMethodsOnly属性默认为true,如果当前方法不是public修饰,返回空
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }
 
    // 如果method是接口中的方法,则获取子类中的方法
   // The method may be on an interface, but we need attributes from the target class.
   // If the target class is null, the method will be unchanged.
   Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
 
   // First try is the method in the target class.
   TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
   if (txAttr != null) {
      return txAttr;
   }
 
    // 方法上没有@Transactionl注解,尝试从类上获取
    // Second try is the transaction attribute on the target class.
   txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
   if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
      return txAttr;
   }
 
   if (specificMethod != method) {
      // Fallback is to look at the original method.
      txAttr = findTransactionAttribute(method);
      if (txAttr != null) {
         return txAttr;
      }
      // Last fallback is the class of the original method.
      txAttr = findTransactionAttribute(method.getDeclaringClass());
      if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
         return txAttr;
      }
   }
 
   return null;
}

org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#determineTransactionAttribute

这里this.annotationParsers就是上面提到的事务属性解析器,实际只有一个SpringTransactionAnnotationParser

@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
   for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
      TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
      if (attr != null) {
         return attr;
      }
   }
   return null;
}
 
 
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
    // 获取方法上的@Transactionl注解属性
   AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
         element, Transactional.class, false, false);
   if (attributes != null) {
      return parseTransactionAnnotation(attributes);
   }
   else {
      return null;
   }
}

顺便再提一下DataSourceTransactionManagerAutoConfiguration,引入了事务管理器,类型是DataSourceTransactionManager

@Bean
@ConditionalOnMissingBean(PlatformTransactionManager.class)
public DataSourceTransactionManager transactionManager(
      DataSourceProperties properties) {
   DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(
         this.dataSource);
   if (this.transactionManagerCustomizers != null) {
      this.transactionManagerCustomizers.customize(transactionManager);
   }
   return transactionManager;
}

你可能感兴趣的:(4、Spring事务 初始化)