项目开发中经常会遇到读写分离等多数据源配置的需求,在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. winform用户控件、动态创建添加控件、timer控件、控件联动

    用户控件: 相当于自定义的一个panel 里面可以放各种其他控件,并可以在后台一下调用整个此自定义控件. 使用方法:在项目上右键.添加.用户控件,之后用户控件的编辑与普通容器控件类似.如果要在后台往窗 ...

  2. [转载]config文件的一个很好的实现

    以下是转载于网上的一个很好的config文件的实现,留存以备案 //Config.h #pragma once #include <string> #include <map> ...

  3. linux vi命令

    >>>>>>>>>>>>>>>>>>>> 2016.12.6: vi是交互式的编 ...

  4. 【转】iOS学习之容易造成循环引用的三种场景

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

  5. Leetcode Valid Sudoku

    Determine if a Sudoku is valid, according to: Sudoku Puzzles - The Rules. The Sudoku board could be ...

  6. Android入门(二):Android的系统架构

    android的系统架构和其操作系统一样,采用了分层的架构.从架构图看,android分为四个层,从高层到低层分别是应用程序层.应用程序框架层.系统运行库层和linux核心层.   从技术方面看,An ...

  7. Ajax缓存解决办法(转载)

    项目有时要用一些Ajax的效果,因为比较简单,也就没有去用什么Ajax.NET之类的东西,手写代码也就实现了.. 第二天,有人向我报告错误:说是只有第一次读取的值正常,后面的值都不正常:我调试了一下 ...

  8. 20145205 《Java程序设计》第7周学习总结

    教材学习内容总结 认识时间与日期 1.格林威治时间(GMT):通过观察太阳而得,因为地球公转轨道为椭圆形且速度不一,本身自传减速而造成误差. 2.世界时(UT):通过观测远方星体跨过子午线而得,受地球 ...

  9. struts基于ognl的自动类型转换需要注意的地方

    好吧,坎坷的过程我就不说了,直接上结论: 在struts2中使用基于ognl的自动类型转换时,Action中的对象属性必须同时添加get/set方法. 例如: 客户端表单: <s:form ac ...

  10. hibernate关联关系笔记

    Hibernate关联关系笔记 单向N:1 *  有连接表:在N方使用<join>/<many-to-one>.1方无需配置与之关联的持久化类. *  没有连接表:在N方使用& ...