【工具型框架】Mybatis——session管理原理/cache管理原理/datasource管理原理/Tran事务管理原理

Mybatis组件——Session管理

Session保存——SqlSessionManager

SqlSessionManager 用于管理session,保存session和提供session,通过调用factory

public class SqlSessionManager implements SqlSessionFactory, SqlSession {
     
  private final SqlSessionFactory sqlSessionFactory;
  private final SqlSession sqlSessionProxy;
  /* 
    localSqlSession保存了正在运行的session
   */
  private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<>();
  private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
     
    this.sqlSessionFactory = sqlSessionFactory;
    this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[]{
     SqlSession.class},
        new SqlSessionInterceptor());
  }
 }

Session创建——DefaultSqlSessionFactory

需要创建和返回session,算是一个函数行为

public class DefaultSqlSessionFactory implements SqlSessionFactory {
     
    /*
      (1)从外部的某一个连接直接创建session
     */
	private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
     
    try {
     
      boolean autoCommit;
      try {
     
        autoCommit = connection.getAutoCommit();
      } catch (SQLException e) {
     
        autoCommit = true;
      }
      /*
        获取环境对象,保存了很多基础配置
       */
      final Environment environment = configuration.getEnvironment();
      /*
        获取事务工厂以及事务
       */
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      final Transaction tx = transactionFactory.newTransaction(connection);
      final Executor executor = configuration.newExecutor(tx, execType);
      /*
      . 创建session
       */
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
     
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
     
      ErrorContext.instance().reset();
    }
  }
}
 /*
    (2)从数据源连接池中获取连接创建session
  */
 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     
    Transaction tx = null;
    try {
     
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);//创建session
    } catch (Exception e) {
     
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
     
      ErrorContext.instance().reset();
    }
}

sesson的代理

利用原生查询时会调用

代理的创建

public class SqlSessionManager implements SqlSessionFactory, SqlSession {
     
  private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
     
    this.sqlSessionFactory = sqlSessionFactory;
    /*
      Proxy.newProxyInstance JDK内部的代理工具类
     */
    this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[]{
     SqlSession.class},
        new SqlSessionInterceptor());
  }
}

拦截器代理实现

 private class SqlSessionInterceptor implements InvocationHandler {
     
    public SqlSessionInterceptor() {
     
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     
      final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();
      if (sqlSession != null) {
     
        try {
     
          return method.invoke(sqlSession, args);
        } catch (Throwable t) {
     
          throw ExceptionUtil.unwrapThrowable(t);
        }
      } else {
     
        try (SqlSession autoSqlSession = openSession()) {
     
          try {
     
            final Object result = method.invoke(autoSqlSession, args);
            autoSqlSession.commit();//提交
            return result;
          } catch (Throwable t) {
     
            autoSqlSession.rollback();//回滚事务
            throw ExceptionUtil.unwrapThrowable(t);
          }
        }
      }
    }
  }

调用

public class SqlSessionManager implements SqlSessionFactory, SqlSession {
     
  public <T> T selectOne(String statement) {
     
    return sqlSessionProxy.selectOne(statement);
  }

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

  @Override
  public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
     
    return sqlSessionProxy.selectMap(statement, mapKey);
  }

  @Override
  public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
     
    return sqlSessionProxy.selectMap(statement, parameter, mapKey);
  }

  @Override
  public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
     
    return sqlSessionProxy.selectMap(statement, parameter, mapKey, rowBounds);
  }
}

Session调用——Excutuor

DefaultSqlSession 是四大对象的最外层,其中Excutuor接管了一些关于sql的管理

public class DefaultSqlSession implements SqlSession {
     

  private final Configuration configuration;
  private final Executor executor;

  private final boolean autoCommit;
  private boolean dirty;
  private List<Cursor<?>> cursorList;

  public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
     
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }/*
      回滚事务
   */
    public void rollback(boolean force) {
     
    try {
     
    /*
      都是调用executor去执行
     */
      executor.rollback(isCommitOrRollbackRequired(force));
      dirty = false;
    } catch (Exception e) {
     
      throw ExceptionFactory.wrapException("Error rolling back transaction.  Cause: " + e, e);
    } finally {
     
      ErrorContext.instance().reset();
    }
  }
 /*
    关闭连接
   */
  @Override
  public void close() {
     
    try {
     
      /*
      都是调用executor去执行
     */
      executor.close(isCommitOrRollbackRequired(false));
      closeCursors();
      dirty = false;
    } finally {
     
      ErrorContext.instance().reset();
    }
  }
  /*
    暴露给mapper代理的调用,这个很重要,接口注入mapper的实现我
   */
  public <T> T getMapper(Class<T> type) {
     
    return configuration.<T>getMapper(type, this);
  }
}

Session拿出——MapperFactoryBean

我们一般开发都是接口注入,mapper处理的时候回将这个接口替换成MapperFactoryBean的getObject返回的类

MapperScannerConfigurer

mapper扫包的时候回去修改Bean的元定义信息把sqlSessionTemplate的实现类搞到MapperFactoryBean内部去

public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {
     
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
     
    if (this.processPropertyPlaceHolders) {
     
      processPropertyPlaceHolders();
    }
    ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
    scanner.setAddToConfig(this.addToConfig);
    scanner.setAnnotationClass(this.annotationClass);
    scanner.setMarkerInterface(this.markerInterface);
    scanner.setSqlSessionFactory(this.sqlSessionFactory);//调用setSqlSessionFactory来创建模板,优先级低
    scanner.setSqlSessionTemplate(this.sqlSessionTemplate);//注册sqlSessionTempalte模板,优先级高
    scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
    scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
    scanner.setResourceLoader(this.applicationContext);
    scanner.setBeanNameGenerator(this.nameGenerator);
    scanner.registerFilters();
    scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
  }
}

MapperFactoryBean实现

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

SqlSessionDaoSupport父类

public abstract class SqlSessionDaoSupport extends DaoSupport {
     
  private SqlSessionTemplate sqlSessionTemplate;
  public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
     
    if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
     
      this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
    }
  }
  public SqlSession getSqlSession() {
     
    return this.sqlSessionTemplate;
  }
  protected SqlSessionTemplate createSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
     
    return new SqlSessionTemplate(sqlSessionFactory);
  }
}

SqlSessionTemplate实现

跟DefalutSession一样,只是事务已经被Spring接管

public class SqlSessionTemplate implements SqlSession, DisposableBean {
     
  private final SqlSessionFactory sqlSessionFactory;
  private final ExecutorType executorType;
  private final SqlSession sqlSessionProxy;
  private final PersistenceExceptionTranslator exceptionTranslator;
    @Override
  public void commit(boolean force) {
     
    throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void rollback() {
     
    throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
  }

  /**
   * {@inheritDoc}
   */
  @Override
  public void rollback(boolean force) {
     
    throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
  }
}

Mybatis组件——Cache缓存管理

一级缓存,session内部的缓存

public abstract class BaseExecutor implements Executor {
     
  protected Transaction transaction;
  protected Executor wrapper;
  protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
  /*
    缓存存储的地方
   */
  protected PerpetualCache localCache;
   /*
    初始化
   */
     protected BaseExecutor(Configuration configuration, Transaction transaction) {
     
    this.transaction = transaction;
    this.deferredLoads = new ConcurrentLinkedQueue<>();
    this.localCache = new PerpetualCache("LocalCache");
    this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");//这里创建
    this.closed = false;
    this.configuration = configuration;
    this.wrapper = this;
  }
  /*
    创建缓存
   */
  private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
     
    List<E> list;
     /*
      localCache.putObject
    */
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
     
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
     
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
     
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
 }
  /*
    利用缓存
   */
     public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
     
    List<E> list;
    try {
     
      queryStack++;
      /*
        localCache.getObject(key),先查询缓存
       */
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
     
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
     
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
     
      queryStack--;
    }
    if (queryStack == 0) {
     
      for (DeferredLoad deferredLoad : deferredLoads) {
     
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
     
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }

缓存本身的实现

public class PerpetualCache implements Cache {
     
  private final String id;
  private Map<Object, Object> cache = new HashMap<>();
  public void putObject(Object key, Object value) {
     
    cache.put(key, value);
  }
  public Object getObject(Object key) {
     
    return cache.get(key);
  }
  public Object removeObject(Object key) {
     
    return cache.remove(key);
  }
}

二级缓存,session内部的缓存

当我们的配置文件配置了cacheEnabled=true时,就会开启二级缓存,二级缓存是mapper级别的
缓存的刷新以及大小控制,我们这里不深究

CachingExecutor的创建

public class Configuration {
     
 public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
     
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
     
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
     
      executor = new ReuseExecutor(this, transaction);
    } else {
     
      executor = new SimpleExecutor(this, transaction);
    }
    /*
      二级缓存如果开启就创建CachingExecutor
     */
    if (cacheEnabled) {
     
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
}

CachingExecutor的实现

public class CachingExecutor implements Executor {
     

  private final Executor delegate;
  private final TransactionalCacheManager tcm = new TransactionalCacheManager();public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
      throws SQLException {
     
    /*
      利用缓存
     */
    Cache cache = ms.getCache();
    if (cache != null) {
     
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) {
     
        ensureNoOutParams(ms, boundSql);
        @SuppressWarnings("unchecked")
      /*
         利用缓存
       */
        List<E> list = (List<E>) tcm.getObject(cache, key);
        if (list == null) {
     
          list = delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
            /*
               创建缓存
           */
          tcm.putObject(cache, key, list); // issue #578 and #116
        }
        return list;
      }
    }
    return delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }
}

缓存管理器的实现

public class TransactionalCacheManager {
     
  private final Map<Cache, TransactionalCache> transactionalCaches = new HashMap<>();
  public void clear(Cache cache) {
     
    getTransactionalCache(cache).clear();
  }
  public Object getObject(Cache cache, CacheKey key) {
     
    return getTransactionalCache(cache).getObject(key);
  }
  public void putObject(Cache cache, CacheKey key, Object value) {
     
    getTransactionalCache(cache).putObject(key, value);
  }
  public void commit() {
     
    for (TransactionalCache txCache : transactionalCaches.values()) {
     
      txCache.commit();
    }
  }
  public void rollback() {
     
    for (TransactionalCache txCache : transactionalCaches.values()) {
     
      txCache.rollback();
    }
  }
  private TransactionalCache getTransactionalCache(Cache cache) {
     
    return transactionalCaches.computeIfAbsent(cache, TransactionalCache::new);
  }
}

缓存本身的实现

public class TransactionalCache implements Cache {
     

  private static final Log log = LogFactory.getLog(TransactionalCache.class);

  private final Cache delegate;
  private boolean clearOnCommit;
  private final Map<Object, Object> entriesToAddOnCommit;
  private final Set<Object> entriesMissedInCache;
    @Override
  public ReadWriteLock getReadWriteLock() {
     
    return null;
  }

  @Override
  public void putObject(Object key, Object object) {
     
    entriesToAddOnCommit.put(key, object);
  }

  @Override
  public Object removeObject(Object key) {
     
    return null;
  }
}

Mybatis组件——Datasource

Datasource的创建

datasource主要由Spring创建的时候调用方法读取配置文件完成对象创建,我们主要看他的实现类

【工具型框架】Mybatis——session管理原理/cache管理原理/datasource管理原理/Tran事务管理原理_第1张图片
UnpooledDataSource

public class UnpooledDataSource implements DataSource {
     
  private ClassLoader driverClassLoader;
  private Properties driverProperties;
  /*
    连接池被放在这里ConcurrentHashMap里面
   */
  private static Map<String, Driver> registeredDrivers = new ConcurrentHashMap<>();
  private Connection doGetConnection(String username, String password) throws SQLException {
     
    Properties props = new Properties();
    if (driverProperties != null) {
     
      props.putAll(driverProperties);
    }
    if (username != null) {
     
      props.setProperty("user", username);
    }
    if (password != null) {
     
      props.setProperty("password", password);
    }
    return doGetConnection(props);
  }

  private Connection doGetConnection(Properties properties) throws SQLException {
     
    initializeDriver();
    Connection connection = DriverManager.getConnection(url, properties);
    configureConnection(connection);
    return connection;
  }
}

PooledDataSource

public class PooledDataSource extends AbstractDataSource {
     
  /*
    连接池被放在这里Queue里面
   */
	private Queue<PooledConnection> freePool;
	private int activeCount; // 活跃连接数
	private DbConfig config;
		private PooledConnection getConnectionDirect() throws SQLException {
     
		if (null == freePool) {
     
			throw new SQLException("PooledDataSource is closed!");
		}

		final int maxActive = config.getMaxActive();
		if (maxActive <= 0 || maxActive < this.activeCount) {
     
			// 超过最大使用限制
			throw new SQLException("In used Connection is more than Max Active.");
		}

		PooledConnection conn = freePool.poll();
		if (null == conn || conn.open().isClosed()) {
     
			conn = this.newConnection();
		}
		activeCount++;
		return conn;
	}
}

Datasource的取出

datasource创建好后就会注入到Environment 对象中,随时拿出

public class DefaultSqlSessionFactory implements SqlSessionFactory {
     
	 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     
    Transaction tx = null;
    try {
     
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      /*
        从Environment拿出datasource然后给事务去管理
       */
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
     
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
     
      ErrorContext.instance().reset();
    }
}

Datasource的利用

dotasourece注入到事务中被事务利用

public class SpringManagedTransaction implements Transaction {
     
 public Connection getConnection() throws SQLException {
     
    if (this.connection == null) {
     
      openConnection();
    }
    return this.connection;
  }
  private void openConnection() throws SQLException {
     
    this.connection = DataSourceUtils.getConnection(this.dataSource);
    this.autoCommit = this.connection.getAutoCommit();
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
    LOGGER.debug(() ->
        "JDBC Connection ["
            + this.connection
            + "] will"
            + (this.isConnectionTransactional ? " " : " not ")
            + "be managed by Spring");
  }
  public void commit() throws SQLException {
     
    if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
     
      LOGGER.debug(() -> "Committing JDBC Connection [" + this.connection + "]");
      this.connection.commit();
    }
  }
   public void rollback() throws SQLException {
     
    if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
     
      LOGGER.debug(() -> "Rolling back JDBC Connection [" + this.connection + "]");
      this.connection.rollback();
    }
  }
}

Mybatis组件——Transaction

事务管理器注入

public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
     
	protected SqlSessionFactory buildSqlSessionFactory() throws Exception {
     
	      /*
	        默认使用spring事务管理器的工厂
	       */
		  configuration.setEnvironment(new Environment(this.environment,
            this.transactionFactory == null ? new SpringManagedTransactionFactory() : this.transactionFactory,
            this.dataSource));
    }
}

事务管理器详情

利用工厂创建Spring事务

public class SpringManagedTransactionFactory implements TransactionFactory {
     
 /*
  创建spring事务
  */
  public Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit) {
     
    return new SpringManagedTransaction(dataSource);
  }
  public Transaction newTransaction(Connection conn) {
     
    throw new UnsupportedOperationException("New Spring transactions require a DataSource");
  }
  public void setProperties(Properties props) {
     
  }
}

主要利用connection 完成事务控制,稍后我们详细分析这个

public class SpringManagedTransaction implements Transaction {
     
  public void commit() throws SQLException {
     
    if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
     
      LOGGER.debug(() -> "Committing JDBC Connection [" + this.connection + "]");
      this.connection.commit();
    }
  }
  public void rollback() throws SQLException {
     
    if (this.connection != null && !this.isConnectionTransactional && !this.autoCommit) {
     
      LOGGER.debug(() -> "Rolling back JDBC Connection [" + this.connection + "]");
      this.connection.rollback();
    }
  }
}

事务管理器调用

public class DefaultSqlSessionFactory implements SqlSessionFactory {
     
	private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
     
    Transaction tx = null;
    try {
     
      final Environment environment = configuration.getEnvironment();
      /*
        获取事务工厂
       */
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
        /*
        创建事务
       */
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
       /*
        注入事务
       */
       final Executor executor = configuration.newExecutor(tx, execType);
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
     
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
     
      ErrorContext.instance().reset();
    }
  }
}

事务管理器干预

Spring的注解式事务是如何干预,这个创建过程呢

SpringManagedTransaction

获取连接的时候回调用DataSourceUtils然后传datasource进去拿

public class SpringManagedTransaction implements Transaction {
     
  private void openConnection() throws SQLException {
     
    this.connection = DataSourceUtils.getConnection(this.dataSource);
    this.autoCommit = this.connection.getAutoCommit();
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);

    LOGGER.debug(() ->
        "JDBC Connection ["
            + this.connection
            + "] will"
            + (this.isConnectionTransactional ? " " : " not ")
            + "be managed by Spring");
  }
}

DataSourceUtils

调用TransactionSynchronizationManager,里面是静态变量存储本地线程实现Spring事务和mybatis的资源共享
什么是资源的同步呢?在一个事务中我们往往会一次执行多个SQL(如果是单条的SQL实际上没有必要开启事务),为了保证事务所有的SQL都能够使用一个数据库连接,这个时候我们需要将数据库连接跟事务进行同步,这个时候数据库连接就是跟这个事务同步的一个资源

public abstract class DataSourceUtils {
     
     /*
         获取连接,调用doGetConnection
     */
	public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
     
		try {
     
			return doGetConnection(dataSource);
		}
		catch (SQLException ex) {
     
			throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex);
		}
		catch (IllegalStateException ex) {
     
			throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage());
		}
	}
	public static Connection doGetConnection(DataSource dataSource) throws SQLException {
     
		/*
		  本地变量中如果已经有连接资源则复用他
		 */
		ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
		if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
     
			conHolder.requested();
			if (!conHolder.hasConnection()) {
     
				logger.debug("Fetching resumed JDBC Connection from DataSource");
				conHolder.setConnection(fetchConnection(dataSource));
			}
			return conHolder.getConnection();
		}
		logger.debug("Fetching JDBC Connection from DataSource");
		Connection con = fetchConnection(dataSource);
       	/*
		  否则就创建资源上传到本地变量,但是事务必须是已经开启的勒
		 */
		if (TransactionSynchronizationManager.isSynchronizationActive()) {
     
			try {
     
				// Use same Connection for further JDBC actions within the transaction.
				// Thread-bound object will get removed by synchronization at transaction completion.
				ConnectionHolder holderToUse = conHolder;
				if (holderToUse == null) {
     
					holderToUse = new ConnectionHolder(con);
				}
				else {
     
					holderToUse.setConnection(con);
				}
				holderToUse.requested();
				TransactionSynchronizationManager.registerSynchronization(
						new ConnectionSynchronization(holderToUse, dataSource));
				holderToUse.setSynchronizedWithTransaction(true);
				/*
				 绑定datasouce资源,用于spirng事务用datasource去提交和回滚
				 */
				if (holderToUse != conHolder) {
     
					TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
				}
			}
			catch (RuntimeException ex) {
     
				// Unexpected exception from external delegation call -> close Connection and rethrow.
				releaseConnection(con, dataSource);
				throw ex;
			}
		}

		return con;
	}
}

TransactionSynchronizationManager

在调用一个需要事务的组件的时候,管理器首先判断当前调用(即当前线程)有没有一个事务,如果没有事务则启动一个事务,并把事务与当前线程绑定。Spring使用TransactionSynchronizationManager的bindResource方法将datasouce绑定先本地变量,供给事务最后提交和回滚的时候用到,我们等一下讲一讲他是怎么取出来的

public abstract class TransactionSynchronizationManager {
     

	private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);

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

	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<>("Transaction synchronizations");

	private static final ThreadLocal<String> currentTransactionName =
			new NamedThreadLocal<>("Current transaction name");

	private static final ThreadLocal<Boolean> currentTransactionReadOnly =
			new NamedThreadLocal<>("Current transaction read-only status");

	private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
			new NamedThreadLocal<>("Current transaction isolation level");

	private static final ThreadLocal<Boolean> actualTransactionActive =
			new NamedThreadLocal<>("Actual transaction active");
}

事务管理器就是利用TransactionSynchronizationManager 实现资源绑定,那么我们看看Spring事务如何将事务管理资源放进去呢?

Mybatis组件——Spring事务原理

创建事务

aop*增强器——TransactionAttributeSourceAdvisor

public class TransactionAttributeSourceAdvisor extends AbstractPointcutAdvisor {
     
	private TransactionInterceptor transactionInterceptor;
	public Advice getAdvice() {
     
		Assert.state(this.transactionInterceptor != null, "No TransactionInterceptor set");
		return this.transactionInterceptor;
	}
}

aop通知方法——TransactionInterceptor

实现了MethodInterceptor来实现静态代理

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
     
	public Object invoke(MethodInvocation invocation) throws Throwable {
     
		Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
		return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
	}
}
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
     
		protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
     

		//…………
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
     
		    /*
		      创建事务
		     */
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
     
				retVal = invocation.proceedWithInvocation();//执行业务
			}
			catch (Throwable ex) {
     
				completeTransactionAfterThrowing(txInfo, ex);//回滚事务
				throw ex;
			}
			finally {
     
				cleanupTransactionInfo(txInfo);
			}

			if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
     
				// Set rollback-only in case of Vavr failure matching our rollback rules...
				TransactionStatus status = txInfo.getTransactionStatus();
				if (status != null && txAttr != null) {
     
					retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
				}
			}

			commitTransactionAfterReturning(txInfo);//提交事务
			return retVal;
		}
}
/*
  txInfo.transactionAttribute.rollbackOn可以判断当前异常是否需要回滚来决定回滚,否则就提交事务
 */
	protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) {
     
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
     
			if (logger.isTraceEnabled()) {
     
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
						"] after exception: " + ex);
			}
			if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) {
     
				try {
     
					txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
     
					logger.error("Application exception overridden by rollback exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
     
					logger.error("Application exception overridden by rollback exception", ex);
					throw ex2;
				}
			}
			else {
     
				// We don't roll back on this exception.
				// Will still roll back if TransactionStatus.isRollbackOnly() is true.
				try {
     
					txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
				}
				catch (TransactionSystemException ex2) {
     
					logger.error("Application exception overridden by commit exception", ex);
					ex2.initApplicationException(ex);
					throw ex2;
				}
				catch (RuntimeException | Error ex2) {
     
					logger.error("Application exception overridden by commit exception", ex);
					throw ex2;
				}
			}
		}
	}
	protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
			@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
     
         
		if (txAttr != null && txAttr.getName() == null) {
     
			txAttr = new DelegatingTransactionAttribute(txAttr) {
     
				@Override
				public String getName() {
     
					return joinpointIdentification;
				}
			};
		}
		TransactionStatus status = null;
		/*
		  getTransaction获取事务
		 */
		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");
				}
			}
		}
		/*
		 创建TransactionInfo对象
		 */
		return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
	}
}

Spring事务管理器——AbstractPlatformTransactionManager

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
     
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {
     

		TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
		/*
		  这里回获取datasource
		 */
		Object transaction = doGetTransaction();
		boolean debugEnabled = logger.isDebugEnabled();
		/*
		 事务已经存在
		 */
		if (isExistingTransaction(transaction)) {
     
			return handleExistingTransaction(def, transaction, debugEnabled);
		}
		/*
		 事务超时了
		 */
		if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
     
			throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout());
		}
		if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
     
			throw new IllegalTransactionStateException(
					"No existing transaction found for transaction marked with propagation 'mandatory'");
		}
		/*
		 事务超时了
		 */
		else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
				def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
     
			SuspendedResourcesHolder suspendedResources = suspend(null);
			if (debugEnabled) {
     
				logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def);
			}
			try {
     
			/*
		           创建新的事务
		      */
				return startTransaction(def, transaction, debugEnabled, suspendedResources);
			}
			catch (RuntimeException | Error ex) {
     
				resume(null, suspendedResources);
				throw ex;
			}
		}
		else {
     
			// Create "empty" transaction: no actual transaction, but potentially synchronization.
			if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
     
				logger.warn("Custom isolation level specified but no actual transaction initiated; " +
						"isolation level will effectively be ignored: " + def);
			}
			boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
			return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null);
		}
	}
   private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
			boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
     

		boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
		DefaultTransactionStatus status = newTransactionStatus(
				definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
		doBegin(transaction, definition);
		/*
		  向本地变量注册事务
		 */
		prepareSynchronization(status, definition);
		return status;
	}
	/*
	  事务开启后,mybatis的datasource 发sql语句把datasource放到threadlocal中
	 */
	protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
     
		if (status.isNewSynchronization()) {
     
			TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
			TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
					definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
							definition.getIsolationLevel() : null);
			TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
			TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
			TransactionSynchronizationManager.initSynchronization();
		}
	}
}

获取datasource

继续分析这个方法getTransaction

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
     
	public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException {
     
		//……
		Object transaction = doGetTransaction();
		//……
	}
}
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
     
	/*
	 利用TransactionSynchronizationManager拿出了datasouce被返回一个DataSourceTransactionObject 
	 然后封装在了DefaultTransactionStatus
	 DefaultTransactionStatus封装了TranInfo里面
	 */
	protected Object doGetTransaction() {
     
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		txObject.setConnectionHolder(conHolder, false);
		return txObject;
	}
}

利用datasource

事务只有在回滚以及提交的时候,才会需要用datasource指令

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
     
		protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
     

		//…………
		if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
     
		    /*
		      创建事务
		     */
			TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

			Object retVal;
			try {
     
				retVal = invocation.proceedWithInvocation();//执行业务
			}
			catch (Throwable ex) {
     
				completeTransactionAfterThrowing(txInfo, ex);//回滚事务
				throw ex;
			}
			finally {
     
				cleanupTransactionInfo(txInfo);
			}
			commitTransactionAfterReturning(txInfo);//提交事务
			return retVal;
		}
	/*
	  提交
	 */
	protected void commitTransactionAfterReturning(@Nullable TransactionInfo txInfo) {
     
		if (txInfo != null && txInfo.getTransactionStatus() != null) {
     
			if (logger.isTraceEnabled()) {
     
				logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
			}
			txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
		}
	}
}
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
     
	public final void commit(TransactionStatus status) throws TransactionException {
     
		if (status.isCompleted()) {
     
			throw new IllegalTransactionStateException(
					"Transaction is already completed - do not call commit or rollback more than once per transaction");
		}

		DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
		if (defStatus.isLocalRollbackOnly()) {
     
			if (defStatus.isDebug()) {
     
				logger.debug("Transactional code has requested rollback");
			}
			processRollback(defStatus, false);
			return;
		}

		if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
     
			if (defStatus.isDebug()) {
     
				logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
			}
			processRollback(defStatus, true);
			return;
		}

		processCommit(defStatus);
	}
	private void processCommit(DefaultTransactionStatus status) throws TransactionException {
     
		try {
     
		    //…………
					doCommit(status);
			//…………
	}
}

DataSourceTransactionManager

把在status中的DataSourceTransactionObject 拿出来,然后调用提交方法,至此完成了全流程的事务管理

public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {
     
	protected void doCommit(DefaultTransactionStatus status) {
     
		DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
		Connection con = txObject.getConnectionHolder().getConnection();
		if (status.isDebug()) {
     
			logger.debug("Committing JDBC transaction on Connection [" + con + "]");
		}
		try {
     
			con.commit();
		}
		catch (SQLException ex) {
     
			throw new TransactionSystemException("Could not commit JDBC transaction", ex);
		}
	}
}

以上整个流程就是:
(1)AOP创建事务到ThrealLocal中
(2)发起sql的时候如果发现有事务则bingResouce到ThrealLocal中
(3)当AOP执行过程中发生异常或者执行最后要提交的时候就用ThrealLocal中的Resouce完成混滚

你可能感兴趣的:(互联网底层专题,spring)