spring的事务管理器

事务管理器在实际的开发过程中主要是配合注解的使用,也可以在代码中手动的创建事务管理器,
注解是结合@Transaction注解,手动的可以在网上找一些资料,创建TransactionTemplate手动的调用execute方法.
事务管理器的作用是什么呢,其实就是connection的自动提交设置成false,方法执行结束后统一的commit或者rollback,道理是很简单的.


image.png

如果没有事务管理器,那两条sql语句,就得手动的获取connection,并讲自动提交设置为false,再统一提交或者回滚

 public static void main(String[] args) throws IOException, SQLException, ClassNotFoundException, InstantiationException, IllegalAccessException{
        // 1 提供Properties实例对象
        Properties pros = new Properties();
        FileInputStream fs = new FileInputStream("C:\\Users\\DuoDuo\\Desktop\\codeTest\\springboottest\\src\\main\\resources\\jdbc.properties");
        pros.load(fs);
        // 2 读取配置信息
        String url = pros.getProperty("url");
        String user = pros.getProperty("username");
        String password = pros.getProperty("password");
        String driverClass = pros.getProperty("driver-class-name");
        // 4 加载驱动
        Class<Driver> clazz = (Class<Driver>) Class.forName(driverClass);
        Driver driver = clazz.newInstance();
        // 5 注册驱动
        DriverManager.registerDriver(driver);
        // 6 获取对象
        Connection conn = DriverManager.getConnection(url, user, password);
        // 7 取消自动提交
        conn.setAutoCommit(false);
        // 8 获取Statement
        PreparedStatement preparedStatement = conn.prepareStatement("select * from empage");
        // 9 执行sql  这里省略多条的update语句
        ResultSet resultSet = preparedStatement.executeQuery();
        // 10 打印
        while(resultSet.next()){
            int id = resultSet .getInt("id");
            String ename = resultSet .getString("ename");
            int age = resultSet .getInt("age");
            System.out.println(id+ename+age);
        }
        //11 自动提交 or rollback
        conn.commit();
    }

在spring项目中,可以从容器中获取datasource,再Connection connection = dataSource.getConnection();获取连接,一般都是从连接池中获取连接
从示例中也可以看到,java是如何与数据库交换数据的,PreparedStatement是驱动自己去实现的,本例使用的是mysql驱动

有了事务管理器之后,十分的方便,如果结合了spring只需要一个注解就可以实现,本文重点分析使用注解的方式,结合mybatis是如何工作的
1.数据源datasource
org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari#dataSource
spring默认使用的是HikariDataSource数据源


image.png

2.事务管理器
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration.JdbcTransactionManagerConfiguration#transactionManager
默认使用的是DataSourceTransactionManager


image.png

3.@Transaction如何包装当前类
通过springboot的自动配置特性引入TransactionAutoConfiguration
image.png

spring.factories文件引入TransactionAutoConfiguration配置类
自己通过debug的方式,查看调用链,执行registerAutoProxyCreatorIfNecessary方法

org.springframework.aop.config.AopConfigUtils#registerAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)


image.png

将InfrastructureAdvisorAutoProxyCreator注入近BeanDefinitionMap中
InfrastructureAdvisorAutoProxyCreator是AbstractAutoProxyCreator接口的子类,注意postProcessAfterInitialization这个方法,这是bean的后置处理器,上面提到InfrastructureAdvisorAutoProxyCreator类已经注入进容器里,当创建bean的时候就会调用postProcessAfterInitialization后置处理器
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization中wrapIfNecessary(bean, beanName, cacheKey)方法
当前的bean是否被aop切面命中,图中getAdvicesAndAdvisorsForBean方法判断当前类或者当前类的方法是否标注了@Transaction,如果标注创建代理类,getAdvicesAndAdvisorsForBean也判断了是否被AOP命中,@AspectJ 的几个注解
image.png

spring中默认添加的关于事务的Advisor,Advisor就是aop的切面,pointcut切点,可以去网上查一下资料
如果类中有一个方法标注了@Transaction,当前类就会被代理
image.png

4.sql的执行
cglib代理类的第一个callback是DynamicAdvisedInterceptor
执行标注了@Transaction注解的方法的时候,会被拦截,图中就是DynamicAdvisedInterceptor,chain就是拦截链路TransactionInterceptor
image.png

方法调用之前会被拦截,跳过一些方法,参考图中跳过的方法,调用到doBegin方法
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
image.png

image.png

bindResource方法将连接放到threadlocal中,后续会被获取,因为这里只是创建了一个connection,并没有执行sql,后续再mybatis中从线程中获取连接执行sql
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());


image.png

mybatis的执行
org.apache.ibatis.executor.SimpleExecutor#prepareStatement
image.png

image.png

从threadloacl中获取连接,这就保证了spring事务开启的时候创建的connection和mybatis执行sql使用的connection是同一个,因为spring开启事务的时候的连接取消了自动提交,保证了事务
当方法执行结束后事务的提交
org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning
image.png

事务结束,整体的事务大概的流程就这式样,保证spring开始事务的时候连接和实际执行sql的连接是同一个,并且开启事务的时候取消自动提交,在事务结束的时候提交事务或者回滚.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容