项目开发中经常会遇到读写分离等多数据源配置的需求,在Java项目中可以通过Spring AOP来实现多数据源的切换。

一、Spring事务开启流程

  Spring中通常通过@Transactional来声明使用事务,我们先来研究一下Spring是如何开启事务的。调试代码,可以发现进入事务方法体内前,会进入如下代码:

public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {

    protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable { ...
//开启事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
...
//代理拦截,执行实际方法体
retVal = invocation.proceedWithInvocation();
...
//无异常,则执行事务提交
commitTransactionAfterReturning(txInfo);
... } }

  可以看出方法createTransactionIfNecessary内创建了事务,断点继续追踪进入createTransactionIfNecessary方法体的tm.getTransaction(txAttr),执行代码如下:

@SuppressWarnings("serial")
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable { @Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//获取当前上下文的事务
Object transaction = doGetTransaction();
...
//如果当前事务已存在,则根据事务传播行为来处理子事务
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
return handleExistingTransaction(definition, transaction, debugEnabled);
}
...
//这里开启事务
doBegin(transaction, definition);
...
} }

  如果当前事务未开启,则通过方法doBegin进行开启,方法体:

@SuppressWarnings("serial")
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean { @Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null; try {
//如果当前db连接为空,则获取并设置连接
if (txObject.getConnectionHolder() == null ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
if (con.getAutoCommit()) {
...
//关闭sql自动提交
con.setAutoCommit(false);
}
...
//设置当前事务状态已开启
txObject.getConnectionHolder().setTransactionActive(true);
...
//绑定当前db连接到ThreadLocal中,key为dataSource,为后续事务体内获取连接提供支持
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
...
} } }

  执行到这里事务已经开启,继续事务体内执行其他db操作,进入工具类org.springframework.jdbc.datasource.DataSourceUtils的方法doGetConnection,方法体如下:

public abstract class DataSourceUtils {

    public static Connection doGetConnection(DataSource dataSource) throws SQLException {
...
//如果当前TransactionSynchronizationManager上下文已经存在事务连接资源,则直接使用此连接,否则往下获取连接
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(dataSource.getConnection());
}
return conHolder.getConnection();
}
...
//如果当前事务上下文不存在连接,则新获取
Connection con = dataSource.getConnection(); if (TransactionSynchronizationManager.isSynchronizationActive()) {
//如果当前事务已开启,则将获取到的连接资源绑定到当前TransactionSynchronizationManager上下文中,供事务体内其他db操作使用
...
if (holderToUse != conHolder) {
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
}
}
} }

  所以,使用Spring开启事务,都会在方法体前创建连接并开启事务,事务体内的其他方法均沿用当前上下文的连接,并不会新获取连接,直到事务体运行结束,归还连接。

基于spring的aop实现读写分离与事务配置的更多相关文章

  1. Spring AOP 实现读写分离

    原文地址:Spring AOP 实现读写分离 博客地址:http://www.extlight.com 一.前言 上一篇<MySQL 实现主从复制> 文章中介绍了 MySQL 主从复制的搭 ...

  2. 基于 EntityFramework 的数据库主从读写分离架构 - 目录

    基于 EntityFramework 的数据库主从读写分离架构       回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目 ...

  3. 基于 EntityFramework 的数据库主从读写分离架构(1) - 原理概述和基本功能实现

        回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目录:      src\ NDF.Data.EntityFramew ...

  4. 基于 EntityFramework 的数据库主从读写分离服务插件

    基于 EntityFramework 的数据库主从读写分离服务插件 1. 版本信息和源码 1.1 版本信息 v1.01 beta(2015-04-07),基于 EF 6.1 开发,支持 EF 6.1 ...

  5. 基于 EntityFramework 的数据库主从读写分离架构(2)- 改进配置和添加事务支持

        回到目录,完整代码请查看(https://github.com/cjw0511/NDF.Infrastructure)中的目录:      src\ NDF.Data.EntityFramew ...

  6. linux下mysql基于mycat做主从复制和读写分离之基础篇

    Linux下mysql基于mycat实现主从复制和读写分离1.基础设施 两台虚拟机:172.20.79.232(主) 172.20.79.233(从) 1.1软件设施 mysql5.6.39 , my ...

  7. MySQL中间件之ProxySQL_读写分离/查询重写配置

    MySQL中间件之ProxySQL_读写分离/查询重写配置 Posted on 2016-12-25 by mark blue, mark Leave a comment MySQL 1.闲扯几句 读 ...

  8. 基于Spring的可扩展Schema进行开发自定义配置标签支持

    一.背景 最近和朋友一起想开发一个类似alibaba dubbo的功能的工具,其中就用到了基于Spring的可扩展Schema进行开发自定义配置标签支持,通过上网查资料自己写了一个demo.今天在这里 ...

  9. 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。

    使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务.

随机推荐

  1. PullToRefreshListView相关

    PullToRefresh使用详解(四)--利用回调函数实现到底加载   链接

  2. 基于requests实现极客学院课程爬虫

    背景 本文主要是为了完成极客学院课程<Python 单线程爬虫>中讲师布置的实战作业. 开发环境 操作系统:windows 10 Python :Python 2.7 IDE:PyChar ...

  3. list点击项高亮其他默认

    // 点击项颜色高亮,其他默认 if (position != lastPosition && onClickItemView != null) { TabMenu lastTabMe ...

  4. 【转】HashMap、TreeMap、Hashtable、HashSet和ConcurrentHashMap区别

    转自:http://blog.csdn.net/paincupid/article/details/47746341 一.HashMap和TreeMap区别 1.HashMap是基于散列表实现的,时间 ...

  5. poj1236Network of Schools Tarjan裸题

    其实就是手打了个Tarjan的模板 输出的时候注意是入度为0的点的个数和max(入度0的个数,出度0的个数),在n=1时特判为0即可 ——以后图论要渐渐模板化,方便使用 #include <cs ...

  6. Java关键字

    Java关键字简介 类别 关键字 说明 访问控制 private 私有的 protected 受保护的 public 公共的 类.方法和变量修饰符 abstract 声明抽象 class 类 exte ...

  7. Predicate<T>与Func<T, bool>泛型委托

    引用别人的: static void Main(string[] args) { List<string> l = new List<string>(); l.Add(&quo ...

  8. jquery数组(排序)

    sort(); html: <h3>字符串数组排序前</h3> <div id="show1"></div> <h3>排 ...

  9. VECTOR COMPUTATION

    COMPUTER OR GANIZATION AND ARCHITECTURE DESIGNING FOR PERFORMANCE NINTH EDITION Although the perform ...

  10. JavaScript对象属性(二)

    对象object  例子一: var car = { "wheels":4, "engines":1, "seats":5}; 例子二: v ...