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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 深入理解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;在目标方法执行的时候;执行拦截器链;事务拦截器:


目录
相关文章
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
93 2
|
1天前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
3天前
|
SQL Java 关系型数据库
【SpringFramework】Spring事务
本文简述Spring中数据库及事务相关衍伸知识点。
30 9
|
10天前
|
Java 开发者 Spring
理解和解决Spring框架中的事务自调用问题
事务自调用问题是由于 Spring AOP 代理机制引起的,当方法在同一个类内部自调用时,事务注解将失效。通过使用代理对象调用、将事务逻辑分离到不同类中或使用 AspectJ 模式,可以有效解决这一问题。理解和解决这一问题,对于保证 Spring 应用中的事务管理正确性至关重要。掌握这些技巧,可以提高开发效率和代码的健壮性。
40 13
|
1月前
|
缓存 安全 Java
Spring高手之路26——全方位掌握事务监听器
本文深入探讨了Spring事务监听器的设计与实现,包括通过TransactionSynchronization接口和@TransactionalEventListener注解实现事务监听器的方法,并通过实例详细展示了如何在事务生命周期的不同阶段执行自定义逻辑,提供了实际应用场景中的最佳实践。
48 2
Spring高手之路26——全方位掌握事务监听器
|
1月前
|
存储 缓存 Java
Spring面试必问:手写Spring IoC 循环依赖底层源码剖析
在Spring框架中,IoC(Inversion of Control,控制反转)是一个核心概念,它允许容器管理对象的生命周期和依赖关系。然而,在实际应用中,我们可能会遇到对象间的循环依赖问题。本文将深入探讨Spring如何解决IoC中的循环依赖问题,并通过手写源码的方式,让你对其底层原理有一个全新的认识。
57 2
|
1月前
|
Java 关系型数据库 数据库
京东面试:聊聊Spring事务?Spring事务的10种失效场景?加入型传播和嵌套型传播有什么区别?
45岁老架构师尼恩分享了Spring事务的核心知识点,包括事务的两种管理方式(编程式和声明式)、@Transactional注解的五大属性(transactionManager、propagation、isolation、timeout、readOnly、rollbackFor)、事务的七种传播行为、事务隔离级别及其与数据库隔离级别的关系,以及Spring事务的10种失效场景。尼恩还强调了面试中如何给出高质量答案,推荐阅读《尼恩Java面试宝典PDF》以提升面试表现。更多技术资料可在公众号【技术自由圈】获取。
|
2月前
|
JavaScript Java 关系型数据库
Spring事务失效的8种场景
本文总结了使用 @Transactional 注解时事务可能失效的几种情况,包括数据库引擎不支持事务、类未被 Spring 管理、方法非 public、自身调用、未配置事务管理器、设置为不支持事务、异常未抛出及异常类型不匹配等。针对这些情况,文章提供了相应的解决建议,帮助开发者排查和解决事务不生效的问题。
|
2月前
|
前端开发 Java 开发者
Spring生态学习路径与源码深度探讨
【11月更文挑战第13天】Spring框架作为Java企业级开发中的核心框架,其丰富的生态系统和强大的功能吸引了无数开发者的关注。学习Spring生态不仅仅是掌握Spring Framework本身,更需要深入理解其周边组件和工具,以及源码的底层实现逻辑。本文将从Spring生态的学习路径入手,详细探讨如何系统地学习Spring,并深入解析各个重点的底层实现逻辑。
73 9
|
2月前
|
XML Java 数据库连接
Spring中的事务是如何实现的
Spring中的事务管理机制通过一系列强大的功能和灵活的配置选项,为开发者提供了高效且可靠的事务处理手段。无论是通过注解还是AOP配置,Spring都能轻松实现复杂的事务管理需求。掌握这些工具和最佳实践,能
79 3