深入理解Spring源码之声明式事务

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析DNS,个人版 1个月
全局流量管理 GTM,标准版 1个月
简介: 深入理解Spring源码之声明式事务
声明式事务环境搭建:
  1、导入相关依赖
          数据源、数据库驱动、Spring-jdbc模块
  2、配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
  3、给方法上标注 @Transactional 表示当前方法是一个事务方法;
  4、 @EnableTransactionManagement 开启基于注解的事务管理功能;
  5、配置事务管理器来控制事务;
          @Bean
          public PlatformTransactionManager transactionManager()
  原理:
  1)、@EnableTransactionManagement
              利用TransactionManagementConfigurationSelector给容器中会导入组件
              导入两个组件
              AutoProxyRegistrar
              ProxyTransactionManagementConfiguration
  2)、AutoProxyRegistrar:
              给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;
              InfrastructureAdvisorAutoProxyCreator: 
              利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执
              行方法利用拦截器链进行调用;
  3)、ProxyTransactionManagementConfiguration 做了什么?
              3.1、给容器中注册事务增强器;
                  3.1.1)、事务增强器要用事务注解的信息AnnotationTransactionAttributeSource
                           解析事务注解
                  3.1.2)、事务拦截器:
                           TransactionInterceptor;保存了事务属性信息,事务管理器;他是一个
                      MethodInterceptor;在目标方法执行的时候;执行拦截器链;事务拦截器:
                              3.1.2.1)、先获取事务相关的属性
                              3.1.2.2)、再获取PlatformTransactionManager,如果事先没有添加
                                        指定任何transactionmanger最终会从容器中按照类型获取
                                        一个PlatformTransactionManager;
                              3.1.2.3)、执行目标方法如果异常,获取到事务管理器,利用事务管理
                                         回滚操作;如果正常,利用事务管理器,提交事务

 

 1)、@EnableTransactionManagement

             利用TransactionManagementConfigurationSelector给容器中会导入组件

             导入两个组件

             AutoProxyRegistrar

             ProxyTransactionManagementConfiguration

打来@EnableTransactionManagement的@Import(TransactionManagementConfigurationSelector.class)源码如下:

adviceMode默认是PROXY

public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
  /**
   * {@inheritDoc}
   * @return {@link ProxyTransactionManagementConfiguration} or
   * {@code AspectJTransactionManagementConfiguration} for {@code PROXY} and
   * {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()}, respectively
   */
  @Override
  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的解析

 2)、AutoProxyRegistrar:

             给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;

             InfrastructureAdvisorAutoProxyCreator:

             利用后置处理器机制(postProcessAfterInitialization)在对象创建以后,包装对象,返回一个代理对象(增强器),代                理对象执行方法利用拦截器链进行调用;

AutoProxyRegistrar的源码如下:

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
  private final Log logger = LogFactory.getLog(getClass());
  @Override
  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
    boolean candidateFound = false;
    Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
    for (String annoType : annoTypes) {
      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;
        if (mode == AdviceMode.PROXY) {
          AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
          if ((Boolean) proxyTargetClass) {
            AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
            return;
          }
        }
      }
    }
    if (!candidateFound) {
                      //省略次要代码
    }
  }
}

进入AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

public abstract class AopConfigUtils {
  public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAutoProxyCreatorIfNecessary(registry, null);
  }
  public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
  }
  public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
  }
  public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
  }
  public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
    return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
  }
  public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
    return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
  }
      //忽略非主线代码
}

可以看到最终调用    

public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
        return registerAspectJAutoProxyCreatorIfNecessary(registry, null);
 }

InfrastructureAdvisorAutoProxyCreator 继承自 AbstractAdvisorAutoProxyCreator

顺带提一下AnnotationAwareAspectJAutoProxyCreator是创建AOP代理类里用到的继承AspectJAwareAdvisorAutoProxyCreator

而AspectJAwareAdvisorAutoProxyCreator继承自 AbstractAdvisorAutoProxyCreator

查看AbstractAutoProxyCreator的postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(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;
}

在 wrapIfNecessary方法的wrapIfNecessary 的 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);添加条件断点条件为null!=specificInterceptors

可以看到 根据beanName=userService时对应的增强器为

[org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice org.springframework.transaction.interceptor.TransactionInterceptor@3da05287]

ProxyTransactionManagementConfiguration 的解析

 3)、ProxyTransactionManagementConfiguration 做了什么?

             3.1、给容器中注册事务增强器;

                 3.1.1)、事务增强器要用事务注解的信息AnnotationTransactionAttributeSource

                          解析事务注解

                 3.1.2)、事务拦截器:

                          TransactionInterceptor;保存了事务属性信息,事务管理器;他是一个

                     MethodInterceptor;在目标方法执行的时候;执行拦截器链;事务拦截器:

                             3.1.2.1)、先获取事务相关的属性

                             3.1.2.2)、再获取PlatformTransactionManager,如果事先没有添加

                                       指定任何transactionmanger最终会从容器中按照类型获取

                                       一个PlatformTransactionManager;

                             3.1.2.3)、执行目标方法如果异常,获取到事务管理器,利用事务管理

                                        回滚操作;如果正常,利用事务管理器,提交事务总结

 

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

TransactionInterceptor 继承自TransactionAspectSupport 主要的事务拦截逻辑在下面这个方法

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
  @Override
  public Object invoke(final MethodInvocation invocation) throws Throwable {
    Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
    return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
      @Override
      public Object proceedWithInvocation() throws Throwable {
        return invocation.proceed();
      }
    });
  }
  protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
      throws Throwable {
    // If the transaction attribute is null, the method is non-transactional.
    final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
    final PlatformTransactionManager tm = determineTransactionManager(txAttr);
    final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
    if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
      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.
        retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
        // target invocation exception
        completeTransactionAfterThrowing(txInfo, ex);
        throw ex;
      }
      finally {
        cleanupTransactionInfo(txInfo);
      }
      commitTransactionAfterReturning(txInfo);
      return retVal;
    }else {
      try {
        Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
            new TransactionCallback<Object>() {
              @Override
              public Object doInTransaction(TransactionStatus 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.
                    return new ThrowableHolder(ex);
                  }
                }
                finally {
                  cleanupTransactionInfo(txInfo);
                }
              }
            });
        // Check result: It might indicate a Throwable to rethrow.
        if (result instanceof ThrowableHolder) {
          throw ((ThrowableHolder) result).getThrowable();
        }
        else {
          return result;
        }
      }
      catch (ThrowableHolderException ex) {
        throw ex.getCause();
      }
    }
  }
}

 

总结:通过TransactionInterceptor环绕增强进行事务的增强,即进入目标方法之前开启事务,退出目标方法时提交/回滚事务。开启事务的核心就是从配置的数据源中获取一个数据库连接,关闭自动提交,然后把这个数据库连接绑定到当前线程,供后续使用 TransactionInterceptor保存了事务属性信息,事务管理器;他是一个  MethodInterceptor;在目标方法执行的时候;执行拦截器链;事务拦截器:


相关文章
|
7天前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
24天前
|
Java 关系型数据库 MySQL
Spring 事务失效场景总结
Spring 事务失效场景总结
39 4
|
7天前
|
Java 程序员 数据库连接
女朋友不懂Spring事务原理,今天给她讲清楚了!
该文章讲述了如何解释Spring事务管理的基本原理,特别是针对女朋友在面试中遇到的问题。文章首先通过一个简单的例子引入了传统事务处理的方式,然后详细讨论了Spring事务管理的实现机制。
女朋友不懂Spring事务原理,今天给她讲清楚了!
|
5天前
|
XML Java 数据库
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
这篇文章是Spring5框架的实战教程,详细介绍了事务的概念、ACID特性、事务操作的场景,并通过实际的银行转账示例,演示了Spring框架中声明式事务管理的实现,包括使用注解和XML配置两种方式,以及如何配置事务参数来控制事务的行为。
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
|
7天前
|
前端开发 Java 数据库连接
一天十道Java面试题----第五天(spring的事务传播机制------>mybatis的优缺点)
这篇文章总结了Java面试中的十个问题,包括Spring事务传播机制、Spring事务失效条件、Bean自动装配方式、Spring、Spring MVC和Spring Boot的区别、Spring MVC的工作流程和主要组件、Spring Boot的自动配置原理和Starter概念、嵌入式服务器的使用原因,以及MyBatis的优缺点。
|
23天前
|
Java Spring 容器
Spring Boot 启动源码解析结合Spring Bean生命周期分析
Spring Boot 启动源码解析结合Spring Bean生命周期分析
60 11
|
20天前
|
Java 关系型数据库 MySQL
Spring Boot事务配置管理
主要总结了 Spring Boot 中如何使用事务,只要使用 @Transactional 注解即可使用,非常简单方便。除此之外,重点总结了三个在实际项目中可能遇到的坑点,这非常有意义,因为事务这东西不出问题还好,出了问题比较难以排查,所以总结的这三点注意事项,希望能帮助到开发中的朋友。
|
24天前
|
缓存 Java 程序员
spring IoC 源码
spring IoC 源码
39 3
|
1月前
|
Java 数据库连接 API
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
Spring事务管理嵌套事务详解 : 同一个类中,一个方法调用另外一个有事务的方法
|
1月前
|
Java Spring
spring 事务控制 设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
spring 事务控制 设置手动回滚 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();