Spring源码之@Transactional源码解析一

目录

 

一、开启事务需要哪些步骤

一、开启事务入口类 @EnableTransactionManagement

二、切面的生成相关逻辑:

三、切点PointCut 

四、Advice 增强逻辑:

五、工具类作用--TransactionSynchronizationManager

六、总结:


一、开启事务需要哪些步骤

一、开启事务入口类 @EnableTransactionManagement

 这注解中的都做了那些事?

首先通过Import的方式将这个事务切面入口类TransactionManagementConfigurationSelector 变成beandefinition对象,接下来进入源码初探:

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) {
//ProxyTransactionManagementConfiguration 切面相关的东西
         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这个类中看一下都做了那些事? 主要方法  registerBeanDefinitions

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) {
            //注册AOp的入口类 InfrastructureAdvisorAutoProxyCreator    没有入口类不能生成代理
            AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
            if ((Boolean) proxyTargetClass) {
            //把属性设置到入口类中,最终会copy到prosyFactory中
               AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
               return;
            }
         }
      }
   }
   //省略.....
}

生成事务切面。切面(Advisor)中的两个核心要素,切点(PointCut)和增强(Advice),任何切面都有的,是切面中的一种规范

二、切面的生成相关逻辑:

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();
    //切面里面设置处理事务的属性对象   transactionAttributeSource()方法返回一个TransactionAttributeSource对象,这个对象呢是解析@Transaction注解的并且封装成TransactionAttribute
    //对象
      advisor.setTransactionAttributeSource(transactionAttributeSource());
    //设置切面中的advice
      advisor.setAdvice(transactionInterceptor());
    //设置切面排序,通过@EnableTransactionManagement注解中的属性可以设置
      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() {
     //创建事务增强  实现了 MethodInterceptor接口
      TransactionInterceptor interceptor = new TransactionInterceptor();
    //事务属性管理器设置到davice中
      interceptor.setTransactionAttributeSource(transactionAttributeSource());
      if (this.txManager != null) {
    //设置事务管理器  这个属性是在父类中
         interceptor.setTransactionManager(this.txManager);
      }
      return interceptor;
   }

}

三、切点PointCut 

在bean实例化最后判断是否生成代理的逻辑中要进行判断matches,一个是ClassFilter,这个是默认是true,另一个是MethodMaches,这个是主要的判断逻辑,如下: 类 TransactionAttributeSourcePointcut

@Override
public boolean matches(Method method, Class<?> targetClass) {
   if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
      return false;
   }
   TransactionAttributeSource tas = getTransactionAttributeSource();
//只要方法上面能拿到实物属性就返回true,就生成代理
   return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

核心代码 在类AbstractFallbackTransactionAttributeSource中的getTransactionAttribute 方法:

public TransactionAttribute getTransactionAttribute(Method method, 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 {
      // We need to work it out.
     //如果method不是public的返回null
      TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
//省略。。。。
   }
}
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
   // Don't allow no-public methods as required.
   if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
      return null;
   }

   // Ignore CGLIB subclasses - introspect the actual user class.
   Class<?> userClass = ClassUtils.getUserClass(targetClass);
   // 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 = ClassUtils.getMostSpecificMethod(method, userClass);
   // If we are dealing with method with generic parameters, find the original method.
   specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);

   // 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.
  //如果方法上面没有@Transaction注解,则去类上看有没有改注解,这就是为什么前面classfilter直接返回true的原因。逻辑跟方法一样的
   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;
}

下面进入findTransactionAttribute方法直接进入到AnnotationTransactionAttributeSource类中

protected TransactionAttribute determineTransactionAttribute(AnnotatedElement ae) {
   if (ae.getAnnotations().length > 0) {
      for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
        //判断方法上有没有@Transaction注解,并将注解中的属性值封装成key  value形式
         TransactionAttribute attr = annotationParser.parseTransactionAnnotation(ae);
         if (attr != null) {
            return attr;
         }
      }
   }
   return null;
}

四、Advice 增强逻辑:

核心类TransactionInterceptor  实现了 MethodInterceptor接口,肯定会实现invoke方法,只有当代理对象去调用方法时,进入到invoke

@Override
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, new InvocationCallback() {
      @Override
      public Object proceedWithInvocation() throws Throwable {
         //火炬传递
         return invocation.proceed();
      }
   });
}

 下面进入到事务切面中的核心代码逻辑invokeWithinTransaction

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);
   //获取joinpoint
   final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
   //只要是注解事务都会走下面的if
   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. 火炬传递
         retVal = invocation.proceedWithInvocation();
      }
      catch (Throwable ex) {
         // target invocation exception 事务回滚
         completeTransactionAfterThrowing(txInfo, ex);
         throw ex;
      }
      finally {
         cleanupTransactionInfo(txInfo);
      }
     //事务提交
      commitTransactionAfterReturning(txInfo);
      return retVal;
   }

  //省略。。。。。
}

接着是 createTransactionIfNecessary中的核心了逻辑

protected TransactionInfo createTransactionIfNecessary(
      PlatformTransactionManager tm, 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);
}

 重点方法getTransaction  再类中 AbstractPlatformTransactionManage 

public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
   //重点看,。。DataSourceTransactionObject拿到对象,第一次进来为null
   Object transaction = doGetTransaction();


   // Cache debug flag to avoid repeated checks.
   boolean debugEnabled = logger.isDebugEnabled();
  
   if (definition == null) {
      // Use defaults if no transaction definition given.
      definition = new DefaultTransactionDefinition();
   }
   //第一次进来为null,所以不存在事务,判断逻辑是事务对象中有连接并且是active,则说明之前有事务
   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());
   }

   // No existing transaction found -> check propagation behavior to find out how to proceed.
   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 ex) {
         resume(null, suspendedResources);
         throw ex;
      }
      catch (Error err) {
         resume(null, suspendedResources);
         throw err;
      }
   }
   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);
   }
}

DataSourceTransactionObject 对象的组成,在他的父类(JdbcTransactionObjectSupport)中有一个 ConnectionHolder属性,这个ConnectionHolder对象中包装这一个Connection连接。

接下来看一下newTransactionStatus方法的逻辑:

protected DefaultTransactionStatus newTransactionStatus(
      TransactionDefinition definition, Object transaction, boolean newTransaction,
      boolean newSynchronization, boolean debug, Object suspendedResources) {

   boolean actualNewSynchronization = newSynchronization &&
         !TransactionSynchronizationManager.isSynchronizationActive();
  //创建一个新的事务状态  注意这里的newTransaction 为true
   return new DefaultTransactionStatus(
         transaction, newTransaction, actualNewSynchronization,
         definition.isReadOnly(), debug, suspendedResources);
}

开启事务的核心代码逻辑:

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

   try {
//如果事务对象中没有连接对象
      if (!txObject.hasConnectionHolder() ||
            txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
//事务管理器中拿dataSource对象,从dataSource对象中拿连接对象,这里可能是AbstractRoutingDataSource数据源
         Connection newCon = this.dataSource.getConnection();
         if (logger.isDebugEnabled()) {
            logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
         }
//把连接对象设置到事务对象中,新创建的连接对象中属性newConnectionHolder为true
         txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
      }
//设置有事务标识
      txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
      con = txObject.getConnectionHolder().getConnection();

//设置是否只读连接和设置事务隔离级别
      Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
      txObject.setPreviousIsolationLevel(previousIsolationLevel);

      if (con.getAutoCommit()) {
         txObject.setMustRestoreAutoCommit(true);
         if (logger.isDebugEnabled()) {
            logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
         }
//关闭自动提交事务,提交交个spring来做
         con.setAutoCommit(false);
      }
//设置该链接的上一个隔离级别
      prepareTransactionalConnection(con, definition);
//把事务状态设置为true
      txObject.getConnectionHolder().setTransactionActive(true);
//设置超时时间
      int timeout = determineTimeout(definition);
      if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
         txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
      }

      // 如果是一个新事物,建立数据源对象和连接对象的绑定关系,并且将该绑定关系的map设置到ThreadLocal中,结构形如   ThreadLocal<线程id,Map<数据源,连接对象>>,数据源是唯一的
      if (txObject.isNewConnectionHolder()) {
         TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
      }
   }
   catch (Throwable ex) {
      if (txObject.isNewConnectionHolder()) {
         DataSourceUtils.releaseConnection(con, this.dataSource);
         txObject.setConnectionHolder(null, false);
      }
      throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
   }
}

 总结doBegin方法做的操作:

  1. 从数据源中创建事务连接对象,并把事务连接对象设置到事务对象中。
  2. 根据@Transaction注解中的属性设置到连接对象中
  3. 关闭自动提交事务,并建立绑定关系。


五、工具类作用--TransactionSynchronizationManager

  1.  在业务代码中使用的,例如想看当前事务流转到什么情况了,
  2. 判断事务是否已经提交了、回滚了,是不是最新的状态等等(运行过程中判断),这个工具类是给开发人员使用的

六、总结:

学习Spring的事务牢记以下几点:

  1. Spring事务跟数据库连接对象钩挂的。
  2. 新建事务对象DataSourceTransactionObject中的newConnectionHolder属性为True,这个属性在事务提交和回滚时很重要

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring框架中,@Transactional注解用于声明一个方法或类是一个事务方法。它可以被应用在方法级别或类级别,并且具有以下使用方法: 1. 方法级别的@Transactional注解: - 在单个方法上使用@Transactional注解,表示该方法是一个事务方法。 - 当方法被调用时,如果当前没有活动的事务,则会启动一个新的事务。如果已经存在一个活动的事务,则该方法将在该事务的上下文中运行。 - 如果方法成功执行并正常返回,事务将被提交。如果方法抛出异常,则事务将被回滚。 2. 类级别的@Transactional注解: - 在类级别上使用@Transactional注解,表示该类中的所有公共方法都是事务方法。 - 类级别的注解可以被方法级别的注解覆盖,即如果一个方法上有@Transactional注解,则该方法会覆盖类级别的注解。 3. 设置事务属性: - @Transactional注解还可以使用一些属性来配置事务的行为。例如,可以使用propagation属性指定事务的传播行为,默认值为REQUIRED。还可以使用isolation属性指定事务的隔离级别,默认值为DEFAULT。 - 其他可用的属性还包括timeout(指定事务超时时间),readOnly(指定事务是否为只读模式)等。 示例代码: ```java @Service public class MyService { @Transactional public void performTransaction() { // 在这里执行数据库操作 } @Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.READ_COMMITTED) public void performAnotherTransaction() { // 在这里执行数据库操作 } } ``` 在上述示例中,`performTransaction`方法和`performAnotherTransaction`方法都被声明为事务方法。其中,`performTransaction`方法使用默认的事务属性,而`performAnotherTransaction`方法设置了传播行为为REQUIRES_NEW,隔离级别为READ_COMMITTED。这些方法中的数据库操作将在事务的上下文中执行,并根据事务的提交或回滚来保证数据的一致性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值