Spring事务源码分析

事务是什么在Spring初始化bean的接入的

什么时候打开一个Session

什么时候关闭一个Session

Session和ThreadLocal区别和联系

@EnableTransactionManagement

@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
   boolean proxyTargetClass() default false;
   AdviceMode mode() default AdviceMode.PROXY;
   int order() default Ordered.LOWEST_PRECEDENCE;

}

我们的启动类上加上该注解之后,import导入TransactionManagementConfigurationSelector ,它是一个SelectImport接口

public final String[] selectImports(AnnotationMetadata importingClassMetadata) {
   Class<?> annType = GenericTypeResolver.resolveTypeArgument(getClass(), AdviceModeImportSelector.class);
   Assert.state(annType != null, "Unresolvable type argument for AdviceModeImportSelector");

   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 adviceMode = attributes.getEnum(this.getAdviceModeAttributeName());
   String[] imports = selectImports(adviceMode);//调用的抽象AdviceModeImportSelector子类方法
   if (imports == null) {
      throw new IllegalArgumentException(String.format("Unknown AdviceMode: '%s'", adviceMode));
   }
   return imports;
}

TransactionManagementConfigurationSelector

TransactionManagementConfigurationSelector#selectImports

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

注入了两个类

AutoProxyRegistrar implements ImportBeanDefinitionRegistrar

ProxyTransactionManagementConfiguration

AutoProxyRegistrar#registerBeanDefinitions

static {
   APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
   APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
   APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}


@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
   return registerAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry,@Nullable Object source) {

    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry,
                                                              @Nullable Object source) {

    Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

    if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
        BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
        if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
            int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
            int requiredPriority = findPriorityForClass(cls);
            if (currentPriority < requiredPriority) {
                apcDefinition.setBeanClassName(cls.getName());
            }
        }
        return null;
    }

    RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
    beanDefinition.setSource(source);
    beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
    return beanDefinition;
}

ProxyTransactionManagementConfiguration

@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.<Integer>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;
   }

}

BeanFactoryTransactionAttributeSourceAdvisor维护了两个重要跟事务相关属性

AnnotationTransactionAttributeSource

TransactionInterceptor

至于作用后边重点说明!

PlatformTransactionManage

ProxyTransactionManagementConfiguration配置的事务管理器相关信息

public abstract class AbstractTransactionManagementConfiguration implements ImportAware {

   @Nullable
   protected AnnotationAttributes enableTx;

   /**
    * Default transaction manager, as configured through a {@link TransactionManagementConfigurer}.
    */
   @Nullable
   protected PlatformTransactionManager txManager;


   @Override
   public void setImportMetadata(AnnotationMetadata importMetadata) {
      this.enableTx = AnnotationAttributes.fromMap(
            importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false));
      if (this.enableTx == null) {
         throw new IllegalArgumentException(
               "@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
      }
   }

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


   @Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
   @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
   public TransactionalEventListenerFactory transactionalEventListenerFactory() {
      return new TransactionalEventListenerFactory();
   }

那么上面相关的信息TransactionManagementConfigurer,以及PlatformTransactionManager来源是哪里?

答案就是自动注入!

TransactionAutoConfiguration

@Configuration
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
      DataSourceTransactionManagerAutoConfiguration.class,
      Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {

   @Bean
   @ConditionalOnMissingBean
   public TransactionManagerCustomizers platformTransactionManagerCustomizers(
         ObjectProvider<List<PlatformTransactionManagerCustomizer<?>>> customizers) {
      return new TransactionManagerCustomizers(customizers.getIfAvailable());
   }

   @Configuration
   @ConditionalOnSingleCandidate(PlatformTransactionManager.class)
   public static class TransactionTemplateConfiguration {

      private final PlatformTransactionManager transactionManager;

      public TransactionTemplateConfiguration(
            PlatformTransactionManager transactionManager) {
         this.transactionManager = transactionManager;
      }

      @Bean
      @ConditionalOnMissingBean
      public TransactionTemplate transactionTemplate() {
         return new TransactionTemplate(this.transactionManager);
      }

   }

   @Configuration
   @ConditionalOnBean(PlatformTransactionManager.class)
   @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
   public static class EnableTransactionManagementConfiguration {

      @Configuration
      @EnableTransactionManagement(proxyTargetClass = false)
      @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
      public static class JdkDynamicAutoProxyConfiguration {

      }

      @Configuration
      @EnableTransactionManagement(proxyTargetClass = true)
      @ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
      public static class CglibAutoProxyConfiguration {

      }

   }

}

依然没有PlatformTransactionManager,但是类上的注解

@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
Neo4jDataAutoConfiguration.class })

DataSourceTransactionManagerAutoConfiguration
@Configuration
@ConditionalOnClass({ JdbcTemplate.class, PlatformTransactionManager.class })
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceTransactionManagerAutoConfiguration {

   @Configuration
   @ConditionalOnSingleCandidate(DataSource.class)
   static class DataSourceTransactionManagerConfiguration {

      private final DataSource dataSource;

      private final TransactionManagerCustomizers transactionManagerCustomizers;

      DataSourceTransactionManagerConfiguration(DataSource dataSource,
            ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
         this.dataSource = dataSource;
         this.transactionManagerCustomizers = transactionManagerCustomizers
               .getIfAvailable();
      }

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

   }
}

@ConditionalOnSingleCandidate(DataSource.class)
说明DataSource只有一个或者有多个但是有primary的时候才满足条件,那么当你使用多数据源的情况下,需要手工指定TransactionManagement的。

Aop和事务异同

一个PointcutAdvisor类

在这里插入图片描述

Aop和事务在bean查找Advisor和Pointcut过滤

跟SpringAop关联着看,事半功倍
在这里插入图片描述

在这里插入图片描述

都是BeanPostProcessor的子类SmartInstantiationAwareBeanPostProcessor的子类

populateBean

initializeBean

​ invokeAwareMethods

​ invokeInitMethods

​ applyBeanPostProcessorsAfterInitialization

是否包装当前bean 跟AOP一样

AbstractAutoProxyCreator#postProcessAfterInitialization

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) throws BeansException {
   if (bean != null) {
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      if (!this.earlyProxyReferences.contains(cacheKey)) {
         return wrapIfNecessary(bean, beanName, cacheKey);
      }
   }
   return bean;
}
//是否要创建代理
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
    if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
        return bean;
    }
    if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
        return bean;
    }
    if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

    // Create proxy if we have advice.
    Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
    if (specificInterceptors != DO_NOT_PROXY) {
        this.advisedBeans.put(cacheKey, Boolean.TRUE);
        Object proxy = createProxy(
            bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
        this.proxyTypes.put(cacheKey, proxy.getClass());
        return proxy;
    }

    this.advisedBeans.put(cacheKey, Boolean.FALSE);
    return bean;
}

依然是查找适合于该bean的所有的Advisor!!跟AOP一样

AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

protected Object[] getAdvicesAndAdvisorsForBean(
      Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {

   List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
   if (advisors.isEmpty()) {
      return DO_NOT_PROXY;
   }
   return advisors.toArray();
}

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    List<Advisor> candidateAdvisors = findCandidateAdvisors();//①查找Advisor
    List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//②通过pointcut#match方法过滤是否需要将Advisor作为bean通知器
    extendAdvisors(eligibleAdvisors);
    if (!eligibleAdvisors.isEmpty()) {
        eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    }
    return eligibleAdvisors;
}

依然是查找适合于该bean的所有的Advisor!!跟AOP一样

为当前bean查找所有的通知器

AOP和Transaction的分叉口

Transaction 也是所有的通用的 找Advisor接口类型bean的方法

protected List<Advisor> findCandidateAdvisors() {
   Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
   return this.advisorRetrievalHelper.findAdvisorBeans();
}

BeanFactoryAdvisorRetrievalHelper#findAdvisorBeans

public List<Advisor> findAdvisorBeans() {
   // Determine list of advisor bean names, if not cached already.
   String[] advisorNames = this.cachedAdvisorBeanNames;
   if (advisorNames == null) {
      // Do not initialize FactoryBeans here: We need to leave all regular beans
      // uninitialized to let the auto-proxy creator apply to them!
      advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
            this.beanFactory, Advisor.class, true, false);
      this.cachedAdvisorBeanNames = advisorNames;
   }
   if (advisorNames.length == 0) {
      return new ArrayList<>();
   }

   List<Advisor> advisors = new ArrayList<>();
   for (String name : advisorNames) {
      if (isEligibleBean(name)) {
         if (this.beanFactory.isCurrentlyInCreation(name)) {
            if (logger.isDebugEnabled()) {
               logger.debug("Skipping currently created advisor '" + name + "'");
            }
         }
         else {
            try {
               advisors.add(this.beanFactory.getBean(name, Advisor.class));
            }
            catch (BeanCreationException ex) {
               //....
            }
         }
      }
   }
   return advisors;
}

整体逻辑就是从BeanFactory找出所有的Advisor类型的bean

AOP

AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors 重写逻辑如下

protected List<Advisor> findCandidateAdvisors() {
   // Add all the Spring advisors found according to superclass rules.
   List<Advisor> advisors = super.findCandidateAdvisors();
   // Build Advisors for all AspectJ aspects in the bean factory.
   if (this.aspectJAdvisorsBuilder != null) {
      advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
   }
   return advisors;
}

pointcut筛选符合该bean的通知器

AopUtil#canApply

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
   Assert.notNull(pc, "Pointcut must not be null");
   if (!pc.getClassFilter().matches(targetClass)) {
      return false;
   }

   MethodMatcher methodMatcher = pc.getMethodMatcher();
   if (methodMatcher == MethodMatcher.TRUE) {
      return true;
   }

   IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
   if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
      introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
   }

   Set<Class<?>> classes = new LinkedHashSet<>();
   if (!Proxy.isProxyClass(targetClass)) {
      classes.add(ClassUtils.getUserClass(targetClass));
   }
   classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

   for (Class<?> clazz : classes) {
      Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
      for (Method method : methods) {
         if (introductionAwareMethodMatcher != null ?
               introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
               methodMatcher.matches(method, targetClass)) {//只要方法级别匹配就表示匹配
            return true;
         }
      }
   }

   return false;
}

只要方法级别匹配就表示匹配,这意味着:

Aop @Aspect标注的类的生成Pointcut规则匹配当前类的方法,那么这个Advisor就是符合bean的通知器。

事务@Transaction标注的类和方法生成的Pointcut规则匹配当前类的方法,那么这个类就需要被生成代理。

所有某个bean是否需要生成代理,只要某个方法被Pointcut匹配上了,那么该bean就会Advisor就是符合bean的通知器。

总结:

除了调用父类的findCandidateAdvisors(同Transaction的查找Advisor的方式)从BeanFactory中找Advisor类型的bean

返回实现了Advisor接口的bean —即Advisor

返回 --Pointcut

aspectJAdvisorsBuilder#buildAspectJAdvisors()来构建 Advisor -见AOP章节

将@Aspect标注的类,解析出@After/@Before 标注的**方法 **包装成Advisor

将@Aspect标注的类,解析出@After/@Before 标注的注解 Pointcut

BeanFactoryTransactionAttributeSourceAdvisor

前文分析@EnableTransactionManagement注解导入的ProxyTransactionManagementConfiguration配置类

创建的BeanFactoryTransactionAttributeSourceAdvisor通知器

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

@Nullable
private TransactionAttributeSource transactionAttributeSource;

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

这个通知器包含的两个成员:

AnnotationTransactionAttributeSource

TransactionInterceptor

BeanFactoryTransactionAttributeSourceAdvisor的pointcut就是TransactionAttributeSourcePointcut

是个抽象类其matches方法如下:

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

   @Override
   public boolean matches(Method method, @Nullable Class<?> targetClass) {
      if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
         return false;
      }
      TransactionAttributeSource tas = getTransactionAttributeSource();
      return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
   }

委托给了TransactionAttributeSource 即

BeanFactoryTransactionAttributeSourceAdvisor.transactionAttributeSource为AnnotationTransactionAttributeSource—导入的配置类生成的。

AnnotationTransactionAttributeSource#getTransactionAttribute不为空就说明当前Advisor适合于当前bean

我们只需要验证改方法在找@Transactional注解即可!

AnnotationTransactionAttributeSource

在这里插入图片描述

其父类AbstractFallbackTransactionAttributeSource实现getTransactionAttribute方法

method bean的方法 targetClass 为bean的class

public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
   if (method.getDeclaringClass() == Object.class) {
      return null;
   }

   // First, see if we have a cached value.
   Object cacheKey = getCacheKey(method, targetClass);
   Object 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 (TransactionAttribute) cached;
      }
   }
   else {
      //获取
      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.isDebugEnabled()) {
            logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
         }
         this.attributeCache.put(cacheKey, txAttr);
      }
      return txAttr;
   }
}

获取bean方法上的事务属性

protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
   // Don't allow no-public methods as required.
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }
   // ....
   // First try is the method in the target class.
   TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
   if (txAttr != null) {
      return txAttr;
   }

   // Second try is the transaction attribute on the target class.
   txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
   if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
      return txAttr;
   }

   return null;
}

方法必须为public的否则即使有事务属性也白搭

public AnnotationTransactionAttributeSource() {
    this(true);
}

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
    this.publicMethodsOnly = publicMethodsOnly;
    this.annotationParsers = new LinkedHashSet<>(2);
    this.annotationParsers.add(new SpringTransactionAnnotationParser());
    if (jta12Present) {
        this.annotationParsers.add(new JtaTransactionAnnotationParser());
    }
    if (ejb3Present) {
        this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
    }
}

protected TransactionAttribute findTransactionAttribute(Method method) {
   return determineTransactionAttribute(method);
}

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
    for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
        TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
        if (attr != null) {
            return attr;
        }
    }
    return null;
}

委托给xxxTransactionParser来解析属性了,构造方法设置了三个TransactionAnnotationParser,然而

我们未使用jta和ejb 所以只看SpringTransactionAnnotationParser。

SpringTransactionAnnotationParser

调用链如下:

TransactionAttributeSourcePointcut#match

​ AnnotationTransactionSource#getTransactionAtrribute

​ #computeTransactionAttribute

​ #findTransactionAttribute

​ #determineTransactionAttribute

​ #TransactionAnnotationParser#parseTransactionAnnotation

protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
   RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
   Propagation propagation = attributes.getEnum("propagation");
   rbta.setPropagationBehavior(propagation.value());
   Isolation isolation = attributes.getEnum("isolation");
   rbta.setIsolationLevel(isolation.value());
   rbta.setTimeout(attributes.getNumber("timeout").intValue());
   rbta.setReadOnly(attributes.getBoolean("readOnly"));
   rbta.setQualifier(attributes.getString("value"));
   ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<>();
   Class<?>[] rbf = attributes.getClassArray("rollbackFor");
   for (Class<?> rbRule : rbf) {
      RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
      rollBackRules.add(rule);
   }
   String[] rbfc = attributes.getStringArray("rollbackForClassName");
   for (String rbRule : rbfc) {
      RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
      rollBackRules.add(rule);
   }
   Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
   for (Class<?> rbRule : nrbf) {
      NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
      rollBackRules.add(rule);
   }
   String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
   for (String rbRule : nrbfc) {
      NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
      rollBackRules.add(rule);
   }
   rbta.getRollbackRules().addAll(rollBackRules);
   return rbta;
}

就是@Transactional注解的所有属性获取了一遍。

什么时候回滚

rollbackForxx

事务嵌套的

出问题如何不会滚

noRollbackFor

事务嵌套的

在串联一下代码:

Spring事务的在Spring bean的创建过程中的接入点:

AbstractAutowireCapableBeanFactory

populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
	invokeAwareMethods
	invokeInitMethods
	applyBeanPostProcessorsAfterInitialization

InfrastructureAdvisorAutoProxyCreator的父类AbstractAutoProxyCreator#postProcessAfterInitialization#wrapIfNecessary

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
   List<Advisor> candidateAdvisors = findCandidateAdvisors();
   List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
   extendAdvisors(eligibleAdvisors);
   if (!eligibleAdvisors.isEmpty()) {
      eligibleAdvisors = sortAdvisors(eligibleAdvisors);
   }
   return eligibleAdvisors;
}

findCandidateAdvisors 就是Spring AOP和Spring 事务的查找Advisor的分界点

findAdvisorsThatCanApply 就是pointcut匹配的过程 一般是找PointcutAdvisor

现在我们的事务的pointcut–TransactionAttributeSourcePointcut #match方法将当前bean的@Transactional属性解析出来不为空 那么当前Advisor -BeanFactoryTransactionAttributeSourceAdvisor

pointcut的事务属性 TransactionAttributeSource=AnnotationTransactionAttributeSource

生成代理

过程跟AOP一模一样,这里既是大致概括下,具体可以参考下我的AOP文章

AopProxyFactory

ProxyFactory

​ proxyFactory#setAdvisors();//BeanFactoryTransactionAttributeSourceAdvisor

​ 因为有两种Aop代理:JDK的和CGLIB的所以需要在这两者中选择一个,因此有个AopProxyFactory

​ createAopProxy—>getAopProxyFactory //DefaultAopProxyFactory

​ DefaultAopProxyFactory#createAopProxy

​ JdkDynamicAopProxy

​ ObjenesisCglibAopProxy

粗略来讲:当时目标类是个接口或者不是proxyTargetClass=false时候使用Jdk的代理,否则其使用cglib的

AopProxy

不论怎么JdkDynamicAopProxy还是ObjenesisCglibAopProxy都实现了AopProxy接口所以都有getProxy方法

  • AopProxy#getProxy
    • jdk的Proxy.newProxyInstance
    • Enhancer.
      • setSuperClass().
      • setCallbacks()
      • setInterfaces

到次为止事务和AOP生成代理的过程是一致的。

运行阶段

我们的使用方式

@Transactional
public UserModel queryByUid(String uid){
    return userMapper.queryByUid(uid);
}

查询!是的查询的我加了一个@Transactional注解 这个可以测试mybatis一级缓存 ,放这里不影响。

@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
   Object oldProxy = null;
   boolean setProxyContext = false;
   Object target = null;
   TargetSource targetSource = this.advised.getTargetSource();
   try {
      if (this.advised.exposeProxy) {
         // Make invocation available if necessary.
         oldProxy = AopContext.setCurrentProxy(proxy);
         setProxyContext = true;
      }
      // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
      target = targetSource.getTarget();
      Class<?> targetClass = (target != null ? target.getClass() : null);
      //① 获取拦截链条
      List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
      Object retVal;
      //② 当前方法上没有事务(其它方法上有@Transactional或者类上有@Transactional 当前方法没有) 
      if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
         
         Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
         retVal = methodProxy.invoke(target, argsToUse);
      }
      else {
         //③ 我们的方法有@Transactional或者这个类上
         retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
      }
      retVal = processReturnType(proxy, target, method, retVal);
      return retVal;
   }
   finally {
      if (target != null && !targetSource.isStatic()) {
         targetSource.releaseTarget(target);
      }
      if (setProxyContext) {
         // Restore old proxy.
         AopContext.setCurrentProxy(oldProxy);
      }
   }
}

主要逻辑:

  • ①获取拦截链条
    • DefaultAdvisorChainFactory 先从方法找在从类中找
  • ②当前方法上没有事务
    • 其它方法上有@Transactional或者类上有@Transactional 当前方法没有
  • ③ 方法有@Transactional或者这个类上

TransactionInterceptor

运行时拦截逻辑

public Object invoke(final 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, invocation::proceed);
}

主要还是调用了如下的代码逻辑:

protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
      final InvocationCallback invocation) throws Throwable{}

方法中有个接口

@FunctionalInterface
protected interface InvocationCallback {

   Object proceedWithInvocation() throws Throwable;
}

jdk8的新特性

再配合上面调用invocation::proceed就是接口的方法proceedWithInvocation()具体实现逻辑哈!

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 tas = getTransactionAttributeSource();
   final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
   final PlatformTransactionManager tm = determineTransactionManager(txAttr);
   final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

   if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      // Standard transaction demarcation with getTransaction and commit/rollback calls.
       //① 使用或者创建事务
      TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
      Object retVal = null;
      try {
         // This is an around advice: Invoke the next interceptor in the chain.
         // This will normally result in a target object being invoked.
          //② 调用接口的方法,实际是调用上面提过的 proceed方法
         retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
         // target invocation exception
          //③ 会回滚事务?或者依然提交?
         completeTransactionAfterThrowing(txInfo, ex);
         throw ex;
      }
      finally {
         cleanupTransactionInfo(txInfo);
      }
       //④ 提交事务
      commitTransactionAfterReturning(txInfo);
      return retVal;
   }

   else {
      final ThrowableHolder throwableHolder = new ThrowableHolder();

      // It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
      try {
         Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
            TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
            try {
               return invocation.proceedWithInvocation();
            }
            catch (Throwable ex) {
               if (txAttr.rollbackOn(ex)) {
                  // A RuntimeException: will lead to a rollback.
                  if (ex instanceof RuntimeException) {
                     throw (RuntimeException) ex;
                  }
                  else {
                     throw new ThrowableHolderException(ex);
                  }
               }
               else {
                  // A normal return value: will lead to a commit.
                  throwableHolder.throwable = ex;
                  return null;
               }
            }
            finally {
               cleanupTransactionInfo(txInfo);
            }
         });

         // Check result state: It might indicate a Throwable to rethrow.
         if (throwableHolder.throwable != null) {
            throw throwableHolder.throwable;
         }
         return result;
      }
      catch (ThrowableHolderException ex) {
         throw ex.getCause();
      }
      catch (TransactionSystemException ex2) {
         if (throwableHolder.throwable != null) {
            logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
            ex2.initApplicationException(throwableHolder.throwable);
         }
         throw ex2;
      }
      catch (Throwable ex2) {
         if (throwableHolder.throwable != null) {
            logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
         }
         throw ex2;
      }
   }
}

核心流程:

  • ① 使用或者创建事务

  • ② 调用接口的方法,实际是调用上面提过的 proceed方法

  • ③ 会回滚事务?或者依然提交?

  • ④ 提交事务

创建或者使用事务

TransactionInterceptor–>TransactionAspectSupport

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 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");
         }
      }
   }
   return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}

创建TransactionStatus

构建TransactionInfo

创建TransactionStatus

DataSourceTransactionManager
在这里插入图片描述

在本文的开头创建的两个条件:

  • @ConditionalOnSingleCandidate(DataSource.class)
  • @ConditionalOnMissingBean(PlatformTransactionManager.class)
  • 将单个的数据源设置到自己的成员dataSource中

我们的TransactionManagement是DatasourceTransactionManagement

(一个数据源的时候并且没有指定时候默认用的)或者多个的时候你指定了其中一个数据源@Primary的

当有多个数据源需要自己指定事务管理器 这里忽略

具体可以看下前面的TransactionAutoConfiguration 自动配置类

public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
   Object transaction = doGetTransaction();//① 获取事务对象  返回的是Object

   // Cache debug flag to avoid repeated checks.
   boolean debugEnabled = logger.isDebugEnabled();

   if (definition == null) {
      // Use defaults if no transaction definition given.
      definition = new DefaultTransactionDefinition();
   }

    //② 判断事务是否存在 开启了
   if (isExistingTransaction(transaction)) {
      // Existing transaction found -> check propagation behavior to find out how to behave.
      return handleExistingTransaction(definition, transaction, debugEnabled);
   }

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

   // ③ 事务传播行为的判定
   if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
      throw new IllegalTransactionStateException(
            "No existing transaction found for transaction marked with propagation 'mandatory'");
   }
   else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
         definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
         definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
      SuspendedResourcesHolder suspendedResources = suspend(null);
      if (debugEnabled) {
         logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
      }
      try {
         boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
         DefaultTransactionStatus status = newTransactionStatus(
               definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
         doBegin(transaction, definition);
         prepareSynchronization(status, definition);
         return status;
      }
      catch (RuntimeException | Error ex) {
         resume(null, suspendedResources);
         throw ex;
      }
   }
   else {
      // Create "empty" transaction: no actual transaction, but potentially synchronization.
      if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
         logger.warn("Custom isolation level specified but no actual transaction initiated; " +
               "isolation level will effectively be ignored: " + definition);
      }
      boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
      return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
   }
}

主要逻辑:

  • ① 获取事务对象 返回的是Object

  • ② 判断事务是否存在 开启了

    条件:connectionHolder!=null && connectionHolder.transactionActive = true;

    protected boolean isExistingTransaction(Object transaction) {
       DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
       return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
    }
    
    
    • 事务存在

      • 事务传播行为
      • 挂起当前事务
    • 事务不存在

      • 判断事务传播行为
      • 不挂起当前事务
      • 创建事务状态
      • 事务开始
事务是否存在条件判断

前面提过判断是否事务存在的条件是:DataSourceTransactionObject的成员ConnectionHolder

`connectionHolder!=null && connectionHolder.transactionActive = true;

事务不存在

DataSourceTransactionManager

protected Object doGetTransaction() {
   DataSourceTransactionObject txObject = new DataSourceTransactionObject();
   txObject.setSavepointAllowed(isNestedTransactionAllowed());
   ConnectionHolder conHolder =
         (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
   txObject.setConnectionHolder(conHolder, false);
   return txObject;
}

返回的是DataSourceTransactionObject

这里边设置的ConnectionHolder

TransactionSynchronizationManager#getResource就是从threadLocal取一下ConnectionHolder

其实是在后边的代码doBegin开启事务的时候设置的,这里是创建事务状态开始。

private static final ThreadLocal<Map<Object, Object>> resources =
      new NamedThreadLocal<>("Transactional resources");

第一次当然是取不出来的,但是txObject#setConnectionHolder(connectionHolder);

key是DataSource value其实是ConnectionHolder 后边会提到!!!!

key是DataSource value其实是ConnectionHolder 后边会提到!!!!

key是DataSource value其实是ConnectionHolder 后边会提到!!!!

不论如何都会创建一个DataSourceTransactionObject 只是成员ConnnectionHolder为空或者不为空的问题

创建事务状态
protected DefaultTransactionStatus newTransactionStatus(
      TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
      boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {

   boolean actualNewSynchronization = newSynchronization &&
         !TransactionSynchronizationManager.isSynchronizationActive();
   return new DefaultTransactionStatus(
         transaction, newTransaction, actualNewSynchronization,
         definition.isReadOnly(), debug, 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;
}

里边记录的是事务的一些状态:只读事务=false 新事务标识 =true 新同步标识=true 挂起资源=null

事务begin
protected void doBegin(Object transaction, TransactionDefinition definition) {
   DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
   Connection con = null;

   try {
      if (!txObject.hasConnectionHolder() ||
            txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
          //① 从数据库连接池中获取连接
         Connection newCon = obtainDataSource().getConnection();
         if (logger.isDebugEnabled()) {
            logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
         }
         txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
      }

       // ② 同步事务
      txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
      con = txObject.getConnectionHolder().getConnection();
		// ③ 设置事务隔离级别  只读事务(先发送 SET TRANSACTION READ ONLY指令给DB)
      Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
      txObject.setPreviousIsolationLevel(previousIsolationLevel);

      // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
      // so we don't want to do it unnecessarily (for example if we've explicitly
      // configured the connection pool to set it already).
      if (con.getAutoCommit()) {
         txObject.setMustRestoreAutoCommit(true);
         if (logger.isDebugEnabled()) {
            logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
         }
          //④ 设置连接不自动提交
         con.setAutoCommit(false);
      }

      prepareTransactionalConnection(con, definition);
       // ⑤ 事务激活【影响后边mybatis的开启session 与否 】
      txObject.getConnectionHolder().setTransactionActive(true);

       //⑥ 设置事务超时事件
      int timeout = determineTimeout(definition);
      if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
         txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
      }

      // Bind the connection holder to the thread.
      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);
   }
}

主要逻辑:

  • ① 从数据库连接池中获取连接
  • ② 同步事务
  • ③ 设置事务隔离级别 只读事务(先发送 SET TRANSACTION READ ONLY指令给DB)
  • ④ 设置连接不自动提交
  • ⑤ 事务激活【影响后边mybatis的开启session 与否
  • ⑥ 设置事务超时事件
  • ⑦ 绑定资源连接到ThreadLocal
    • TransactionSynchronizationManager.resources = ThreadLocal< Map< Object, Object>>
    • TransactionSynchronizationManager#bindResource
      • resource.set(key是DataSource value是ConnectionHolder) set的是一个map

这段代码终于看到从数据库连接池中获取Connection 执行conn.setAutoCommit(false)这样的代码了!

此时的TransactionStatus构建完毕 连接也获取并绑定到ThreadLocal中了

再回到前面

创建TransactionInfo

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.
      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("Don't need to create transaction for [" + joinpointIdentification +
               "]: This method isn't 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.
   txInfo.bindToThread();
   return txInfo;
}

将事务管理器和事务属性包装成 TransactionInfo

设置TransactionStatus到TransactionInfo中

将TransactionInfo有也绑定到ThreadLocal

private void bindToThread() {
   // Expose current TransactionStatus, preserving any existing TransactionStatus
   // for restoration after this transaction is complete.
   this.oldTransactionInfo = transactionInfoHolder.get();
   transactionInfoHolder.set(this);
}

目前有两个地方使用绑定资源到TreadLocal

  • 一个是DataSourceTransactionObjec#ConnectionHolder的connection

    • TransactionSynchronizationManager.resources
  • 一个是TransactionInfo绑定到线程上线文

    • TransactionInterceptor.transactionInfoHolder

上面的部分是拦截到service的方法之后创建完TransactionInfo,代码再回到拦截入口部分。

在这里插入图片描述

还记得这里的Invocation是谁吧!

CglibAopProxy#interceptor

​ CglibMethodInvocation#proceed

​ TransactionInterceptor#invoke(this)

所以参数上的invocation就是CglibMethodInvocation–>MethodInvocation

public Object invoke(final 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, invocation::proceed);
}

参数上面用的jdk8的新特性参数是个接口,接口实现类是调用CglibMethodInvocation#proceed;

public Object proceed() throws Throwable {
   // We start with an index of -1 and increment early.
   if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
      return invokeJoinpoint();//前面的拦截逻辑执行完,执行业务方法
   }

   Object interceptorOrInterceptionAdvice =
         this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
   if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
      // Evaluate dynamic method matcher here: static part will already have
      // been evaluated and found to match.
      InterceptorAndDynamicMethodMatcher dm =
            (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
      if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
         return dm.interceptor.invoke(this);
      }
      else {
         // Dynamic matching failed.
         // Skip this interceptor and invoke the next in the chain.
         return proceed();
      }
   }
   else {
      // It's an interceptor, so we just invoke it: The pointcut will have
      // been evaluated statically before this object was constructed.
      return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
   }
}

return invokeJoinpoint();//前面的拦截逻辑执行完,执行业务方法

我们的业务方法是我们前面service的方法

@Transactional
public UserModel queryByUid(String uid){
    return userMapper.queryByUid(uid);
}

MyBatis接口生成代理补充

mybatis的方法只有接口为什么能调用数据库执行sql?

@MapperScan 接口会被扫描

mapper接口的beanDefinition#setBeanClass(MapperFactoryBean)

MapperFactoryBean是FactoryBean#getObject

getSqlSession

  • SqlSession --> sqlSessionTemplate(全局的SqlSessionFactory)
    • SqlSessionTemplate
      • SqlSession sqlSessionProxy

sqlSessionTemplate#getMapper

  • MapperProxyFactory#newInstance
    • Proxy#newProxyInstance(classLoader,new Class[]{mapper},MapperProxy)

MapperFactoryBean

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
  public T getObject() throws Exception {
    return getSqlSession().getMapper(this.mapperInterface);
  }
}
public abstract class SqlSessionDaoSupport extends DaoSupport {

  private SqlSession sqlSession;

  private boolean externalSqlSession;

  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
    if (!this.externalSqlSession) {
      this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }
  }

  public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
    this.sqlSession = sqlSessionTemplate;
    this.externalSqlSession = true;
  }

  /**
   * Users should use this method to get a SqlSession to call its statement methods
   * This is SqlSession is managed by spring. Users should not commit/rollback/close it
   * because it will be automatically done.
   *
   * @return Spring managed thread safe SqlSession
   */
  public SqlSession getSqlSession() {
    return this.sqlSession;
  }

SqlSessionTemplate

public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
    PersistenceExceptionTranslator exceptionTranslator) {

  notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
  notNull(executorType, "Property 'executorType' is required");

  this.sqlSessionFactory = sqlSessionFactory;
  this.executorType = executorType;
  this.exceptionTranslator = exceptionTranslator;
  this.sqlSessionProxy = (SqlSession) newProxyInstance(
      SqlSessionFactory.class.getClassLoader(),
      new Class[] { SqlSession.class },
      new SqlSessionInterceptor());
}
MapperProxy

SqlSessionTemplate#getMapper

public <T> T getMapper(Class<T> type) {
  return getConfiguration().getMapper(type, this);
}

Configuration#getMapper

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  return mapperRegistry.getMapper(type, sqlSession);
}

MapperRegistry#getMapper

public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
  final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
  if (mapperProxyFactory == null) {
    throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
  }
  try {
    return mapperProxyFactory.newInstance(sqlSession);
  } catch (Exception e) {
    throw new BindingException("Error getting mapper instance. Cause: " + e, e);
  }
}

接口代理MapperProxy的生成

protected T newInstance(MapperProxy<T> mapperProxy) {
  return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}

public T newInstance(SqlSession sqlSession) {
  final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
  return newInstance(mapperProxy);
}

MapperProxy#invoke

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  try {
    if (Object.class.equals(method.getDeclaringClass())) {
      return method.invoke(this, args);
    } else if (isDefaultMethod(method)) {
      return invokeDefaultMethod(proxy, method, args);
    }
  } catch (Throwable t) {
    throw ExceptionUtil.unwrapThrowable(t);
  }
  final MapperMethod mapperMethod = cachedMapperMethod(method);
  return mapperMethod.execute(sqlSession, args);
}
public Object execute(SqlSession sqlSession, Object[] args) {
  Object result;
  switch (command.getType()) {
    case INSERT: {
    Object param = method.convertArgsToSqlCommandParam(args);
      result = rowCountResult(sqlSession.insert(command.getName(), param));
      break;
    }
    case UPDATE: {
      Object param = method.convertArgsToSqlCommandParam(args);
      result = rowCountResult(sqlSession.update(command.getName(), param));
      break;
    }
    case DELETE: {
      Object param = method.convertArgsToSqlCommandParam(args);
      result = rowCountResult(sqlSession.delete(command.getName(), param));
      break;
    }
    case SELECT:
      if (method.returnsVoid() && method.hasResultHandler()) {
        executeWithResultHandler(sqlSession, args);
        result = null;
      } else if (method.returnsMany()) {
        result = executeForMany(sqlSession, args);
      } else if (method.returnsMap()) {
        result = executeForMap(sqlSession, args);
      } else if (method.returnsCursor()) {
        result = executeForCursor(sqlSession, args);
      } else {
        Object param = method.convertArgsToSqlCommandParam(args);
        result = sqlSession.selectOne(command.getName(), param);
      }
      break;
    case FLUSH:
      result = sqlSession.flushStatements();
      break;
    default:
      throw new BindingException("Unknown execution method for: " + command.getName());
  }
  if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
    throw new BindingException("Mapper method '" + command.getName() 
        + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
  }
  return result;
}

这里边的SqlSession是SqlSessionTemplate 前文提过

SqlSessionTemplate#selectOne

public <T> T selectOne(String statement, Object parameter) {
  return this.sqlSessionProxy.<T> selectOne(statement, parameter);
}

这里边的sqlSessionProxy是SqlsessionTemplate的成员SqlSession

这个变量的初始化就是前面提过的SqlSessionInterceptor

SqlSessionInterceptor

private class SqlSessionInterceptor implements InvocationHandler {
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    SqlSession sqlSession = getSqlSession(
        SqlSessionTemplate.this.sqlSessionFactory,
        SqlSessionTemplate.this.executorType,
        SqlSessionTemplate.this.exceptionTranslator);
    try {
      Object result = method.invoke(sqlSession, args);
      if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
        // force commit even on non-dirty sessions because some databases require
        // a commit/rollback before calling close()
        sqlSession.commit(true);
      }
      return result;
    } catch (Throwable t) {
      Throwable unwrapped = unwrapThrowable(t);
      if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
        // release the connection to avoid a deadlock if the translator is no loaded. See issue #22
        closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
        sqlSession = null;
        Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
        if (translated != null) {
          unwrapped = translated;
        }
      }
      throw unwrapped;
    } finally {
      if (sqlSession != null) {
        closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
      }
    }
  }
}

获取Session

现在三个地方有SqlSession了

  • MapperFactoryBean
    • SqlSession—> SqlSessiontemplate
  • SqlSessionTemplate
    • SqlSession —> SqlSessionInterceptor
  • SqlSessionInterceptor
    • invoke 方法内部
      • 创建的SqlSession DefaultSqlSession 这正干活的

可以想象的是这里开启sqlSession就跟之前在ThreadLocal设置的有关系了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值