项目开发中经常会遇到读写分离等多数据源配置的需求,在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. iframe无刷新跨域并获得返回值

    参考:http://geeksun.iteye.com/blog/1070607 /** * iframe跨域提交大数据 * @param action 跨域地址 * @param arr [ {na ...

  2. AngularJs2 学习之路-笔记1-Atscript Ts ES6包含关系

    Atscript 这门新的语言是由谷歌的Angular团队弄出来的 就是为了编写ng2.0 ng2是个极具前瞻性的尝试 这种激进的革新在于对未来标准的迎合 ng2的标准包括了如下:1 module 2 ...

  3. Go语言 数组

    介绍 Array 是值类型,Slice 和 Map 是引用类型.他们是有很大区别的,尤其是在参数传递的时候. 另外,Slice 和 Map 的变量 仅仅声明是不行的,必须还要分配空间(也就是初始化,i ...

  4. python base64的加密与解密

    Base64编码是一种“防君子不防小人”的编码方式.广泛应用于MIME协议,作为电子邮件的传输编码,生成的编码可逆,后一两位可能有“=”,生成的编码都是ascii字符. 优点:速度快,ascii字符, ...

  5. VMware下虚拟机的转移

    将虚拟机文件夹整个拷贝到另一台电脑上: 打开.vmx文件 打开即可: 注意:Mac系统的虚拟机要先用unlocker206破解,才能运行OS系统.

  6. 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)

    本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...

  7. spring的Scheduled(定时任务)和多线程

    一.前言 在我们日常的开发中,经常用到数据同步的更新,这时我们采用的是spring的定时任务和java的多线程进行数据的更新,进行时实的服务调用. 二.实现思路            1.创建线程类 ...

  8. Using MySQL Connector .NET 6.6.4 with Entity Framework 5

    I had been waiting for the latest MySQL connector for .NET to come out so I can move on to the new a ...

  9. SQL 执行进展优化

    聚集索引扫描 SELECT * FROM C_SY_Ownedstorm 聚集索引扫描比表扫描快 聚集索引扫描:发生于聚集表,也相当于全表扫描操作,但在针对聚集列的条件等操作时,效率会较好. 表扫描 ...

  10. jsonp模拟获取百度搜索相关词汇

    随便写了个jsonp模拟百度搜索相关词汇的小demo,帮助新手理解jsonp的用法. <!DOCTYPE html><html lang="en">< ...