关于spring事务源码的一些小理解

栏目: Java · 发布时间: 5年前

内容简介:由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交、回滚等操作全部交给它来实现先来看下三大接口相关类方法:

1、spring事务的简单概述

由于实现事务功能的方式各不相同,Spring进行了统一的抽象,形成了PlatformTransactionManager事务管理器顶级接口(平台事务管理器),事务的提交、回滚等操作全部交给它来实现

先来看下三大接口

  • PlatformTransactionManager : 事务管理器

  • TransactionDefinition : 事务的一些基础信息,如超时时间、隔离级别、传播属性等

  • TransactionStatus : 事务的一些状态信息,如是否是一个新的事务、是否已被标记为回滚

2 PlatformTransactionManager

相关类方法:

public interface PlatformTransactionManager {
  //获取事务状态
   TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException;
   //事务提交
   void commit(TransactionStatus status) throws TransactionException;
   //事务回滚
   void rollback(TransactionStatus status) throws TransactionException;

}复制代码

继承关系:

PlatformTransactionManager

AbstractPlatformTransactionManager
  DataSourceTransactionManager(重点)
  HibernateTransactionManager
  JpaTransactionManager复制代码

触发不同的事物管理器

springboot对 PlatformTransactionManager的默认配置实现(引用 spring-boot-starter-web中jdbc相关jar

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

   }

}复制代码

通过 @ConditionalOnMissingBean(PlatformTransactionManager.class)这个注解可以直到如果没有手动配置

PlatformTransactionManager即使用默认的子类 DataSourceTransactionManager来管理实务

3、事务传播特性和隔离级别

public interface TransactionDefinition {
事务传播特性:
1、支持事务,如果当前线程没有事务,新建一个事务
  int PROPAGATION_REQUIRED = 0;
2、支持事务,如果当前线程没有事务,则以非事务执行
  int PROPAGATION_SUPPORTS = 1;
3、 当前如果有事务,Spring就会使用该事务;否则会抛出异常
  int PROPAGATION_MANDATORY = 2;
4、如果当前线程存在事务,或者不存在事务,都会新建一个事务,并且新建事务与当前事务是相互隔离的,如果新建事务执行时,会先将当前事务挂起,等新建事务执行完成后,再将放行当前事务,如果新事物出现异常,会正常回滚,但不会影响当前事务
  int PROPAGATION_REQUIRES_NEW = 3;
5、 不支持事务,如果存在事务,则会将当前事务挂起,以非事务执行
  int PROPAGATION_NOT_SUPPORTED = 4;
6、不支持事务,如果当前线程存在事务,将会抛异常
  int PROPAGATION_NEVER = 5;
7、如果当前线程存在事务,则新建一个回滚点,如果出现异常,则会回滚到上一个回滚点,对于当前事务是不受任何影响的。
  int PROPAGATION_NESTED = 6;
//隔离级别:默认的隔离级别(对 mysql 数据库来说就是ISOLATION_ READ_COMMITTED,可以重复读)
  int ISOLATION_DEFAULT = -1;
//隔离级别:读未提交
  int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
//隔离级别:读已提交
  int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
//隔离级别:可重复读
  int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
//隔离级别:序列化  
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
   int TIMEOUT_DEFAULT = -1;
  int getPropagationBehavior();
   int getIsolationLevel();
   int getTimeout();
  boolean isReadOnly();
  @Nullable
  String getName();


}


复制代码

4、为什么说spring事务是aop的一种实现

finishBeanFactoryInitialization(beanFactory);一路向后debug最后可以看到下面的代码
复制代码
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.
   //这里就是获取需要代理的类(如果存在advice)复制代码
//获取bean对应的advice集合。   
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
   if (specificInterceptors != DO_NOT_PROXY) {
      this.advisedBeans.put(cacheKey, Boolean.TRUE);
    //将获取到的advice集合保存到代理对象中并返回。
      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;
}复制代码
这里是创建代理的方法
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
      @Nullable Object[] specificInterceptors, TargetSource targetSource) {

   if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
      AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
   }

   ProxyFactory proxyFactory = new ProxyFactory();
   proxyFactory.copyFrom(this);

   if (!proxyFactory.isProxyTargetClass()) {
      if (shouldProxyTargetClass(beanClass, beanName)) {
         proxyFactory.setProxyTargetClass(true);
      }
      else {
         evaluateProxyInterfaces(beanClass, proxyFactory);
      }
   }
   //将advice封装到 advisors中
   Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
   proxyFactory.addAdvisors(advisors);
    //这里的targetSource就是目标对象,在后面调用的时候会用到
   proxyFactory.setTargetSource(targetSource);
   customizeProxyFactory(proxyFactory);
   proxyFactory.setFrozen(this.freezeProxy);
   if (advisorsPreFiltered()) {
      proxyFactory.setPreFiltered(true);
   }

   return proxyFactory.getProxy(getProxyClassLoader());
}


specificInterceptors是拦截器(如果是aop则是前置后置这些过滤器,如果是事务,则是事务拦截器)
BeanFactoryCacheOperationSourceAdvisor(保存了增强的信息)切面记录是前置,后置等增强拦截器链而事务相关记录的是事务拦截器private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024);保存方法对应的事务信息private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);保存这个bean是否为增强beanif (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {  return bean;}判断这个bean是否为代理类,如果不是直接返回单例和多例的区别:
protected void addSingleton(String beanName, Object singletonObject) {  synchronized (this.singletonObjects) {     this.singletonObjects.put(beanName, singletonObject);     this.singletonFactories.remove(beanName);     this.earlySingletonObjects.remove(beanName);     this.registeredSingletons.add(beanName);  }}将获取到的bean保存到singletonObjects中private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);在每次调用的时候,直接从singletonObjects这个ConcurrentHashMap中获取即可。如果是Prototype在从走一遍单例的流程else if (mbd.isPrototype()) {  // It's a prototype -> create a new instance.  Object prototypeInstance = null;  try {     beforePrototypeCreation(beanName);     prototypeInstance = createBean(beanName, mbd, args);  }  finally {     afterPrototypeCreation(beanName);  }  bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}复制代码

5、事务方法调用

和aop调用一样,最后会调用 TransactionInterceptor的invock方法

public Object invoke(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);
}复制代码

然后会调用父类 TransactionAspectSupportinvokeWithinTransaction方法

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.
         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;
      }
   }
}复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

成为乔布斯

成为乔布斯

[美] 布伦特·施兰德、[美] 里克·特策利 / 陶亮 / 中信出版集团 / 2016-10 / 69.00元

本书描绘了一位多姿多彩的人物将与生俱来的激情与成熟的管理方式相结合,打造出史上最有价值、最受消费者追捧的公司,这本书将彻底改变我们看待乔布斯的方式。 本书推翻了关于史蒂夫·乔布斯的传说和陈词滥调,比如他是天才和混蛋的结合体,暴躁易怒、自私自利,怠慢朋友与家人。本书揭示了这位苹果联合创始人和CEO的家庭生活与职业生涯,并回答了一个关键问题:为什么如此轻狂傲慢、以至于被赶出苹果的年轻人能成为史上......一起来看看 《成为乔布斯》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

URL 编码/解码
URL 编码/解码

URL 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具