Spring,tk-mapper源码阅读
Mybatis的源码学习(一):
前言:
结合spring本次学习会先从spring-mybatis开始分析
在学习mybatis之前,应该要对spring的bean有所了解,本文略过
先贴一下mybatis的配置:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations">
<array>
<value>classpath:mapper/**/*.xml</value>
</array>
</property>
<property name="typeAliasesPackage" value="xxxx.model"/>
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
dialect=mysql
reasonable=true
</value>
</property>
</bean>
</array>
</property>
</bean>
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="xxxx.mapper"/>
</bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
先看第一个配置,配置
<property name="dataSource" ref="dataSource"/>
这段即spring IOC 依赖注入的特性,将数据库的配置信息设置到该set方法中
<property name="mapperLocations">
<array>
<value>classpath:mapper/**/*.xml</value>
</array>
</property>
该属性是扫描mapper的xml配置
<property name="typeAliasesPackage" value="xxxx.model"/>
这个配置即为model(或者entity/domain)类设置别名
<property name="plugins">
<array>
<bean class="com.github.pagehelper.PageHelper">
<property name="properties">
<value>
dialect=mysql
reasonable=true
</value>
</property>
</bean>
</array>
</property>
这个配置是集成了分页的pahelper插件,
配置看完了,现在就开始看java代码了
配置好项目之后,找到SqlSessionFactoryBean然后启动tomcat,为什么要找这个类呢?因为这个类就是spring注入mabatis属性的一个入口(将mybatis和spring整合)
结合上面配置内容
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">


底下的所有操作都是为Configuration设置塞值,为了不影响篇幅冗余,暂且略过这些
说一下下面这句

扫描注册Mapper接口

在初始化的时候已经将mapper解析xml的时候已经将mapper注册为一个mapper bean 了
完成上述操作之后,mapper下的所有接口都已经与xml的namespace匹配上,并且mapper注册为一个代理类
最后一句代码就完成转化

调试到 SqlSessionFactoryBuilder,发现默认创建了 DefaultSqlSessionFactory

建立了sqlSessionFactory
下来是扫描
<bean class="tk.mybatis.spring.mapper.MapperScannerConfigurer">
看一下这个类的继承关系

我们看到了这个类实现了BeanDefinitionRegistryPostProcessor接口,此接口即动态的将Bean的内容进行动态修改
方法实现即在下方

执行完上面那个方法之后,tk-mapper开始往下执行,由于一开始spring在扫描sqlSessionFactoryBuilder的时候就已经把mapper命名空间什么的已经扫描过,所以这块不会再去注册mapperBean

下面的注册mapper接口在前面已经执行过了



接下来注入sqlSession模板类,这个类是通过动态代理的方式获取执行器并执行sql
看下配置
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
spring开始扫描这个配置,打开调试器,看一下SqlSessionTemplate的继承图

它继承了SqlSession接口,还有一个SqlSession对象?这个是什么操作?
看构造方法,原来作者这样的设计是让 sqlSessionProxy代理 对SqlSession进行操作
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory;
this.executorType = executorType;
this.exceptionTranslator = exceptionTranslator;
//代理对象创建执行器,并连接DB进行操作
this.sqlSessionProxy = (SqlSession) newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[] { SqlSession.class },
new SqlSessionInterceptor());
}
/**
* Proxy needed to route MyBatis method calls to the proper SqlSession got
* from Spring's Transaction Manager
* It also unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to
* pass a {@code PersistenceException} to the {@code PersistenceExceptionTranslator}.
*/
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//这里的实际对象是DefaultSqlSession
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
//执行目标方法(即调用Executor并组装成sql进行db操作)
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
// force commit even on non-dirty sessions because some databases require
// a commit/rollback before calling close()
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
不得不说,作者的设计架构是真的很棒
下一文 说一下mybatis的动态代理
Spring,tk-mapper源码阅读的更多相关文章
- Spring 注册BeanPostProcessor 源码阅读
回顾上一篇博客中,在AbstractApplicationContext这个抽象类中,Spring使用invokeBeanFactoryPostProcessors(beanFactory);执行Be ...
- spring framework 4 源码阅读(1) --- 前期准备
在开始看代码之前,需要做的第一件事是下载代码. 在这里:https://github.com/spring-projects/spring-framework 下载完成了发现使用gradle做的源代码 ...
- spring framework 4 源码阅读
前面写了几篇spring 的介绍文章,感觉与主题不是很切合.重新整理下思路,从更容易理解的角度来写下文章. spring 的骨架 spring 的骨架,也是spring 的核心包.主要包含三个内容 1 ...
- spring framework 4 源码阅读(2)---从ClassPathXmlApplicationContext开始
Application初始化日志 15:23:12.790 [main] DEBUG o.s.core.env.StandardEnvironment - Adding [systemProperti ...
- (转) Spring源码阅读 之 Spring整体架构
标签(空格分隔): Spring 声明:本文系转载,原地地址:spring framework 4 源码阅读 Spring骨架 Spring的骨架,也是Spring的核心包.主要包含三个内容 cont ...
- Sping学习笔记(一)----Spring源码阅读环境的搭建
idea搭建spring源码阅读环境 安装gradle Github下载Spring源码 新建学习spring源码的项目 idea搭建spring源码阅读环境 安装gradle 在官网中下载gradl ...
- Spring源码阅读系列总结
最近一段时间,粗略的查看了一下Spring源码,对Spring的两大核心和Spring的组件有了更深入的了解.同时在学习Spring源码时,得了解一些设计模式,不然阅读源码还是有一定难度的,所以一些重 ...
- Bean实例化(Spring源码阅读)-我们到底能走多远系列(33)
我们到底能走多远系列(33) 扯淡: 各位: 命运就算颠沛流离 命运就算曲折离奇 命运就算恐吓着你做人没趣味 别流泪 心酸 更不应舍弃 ... 主题: Spring源码阅读还在继 ...
- 初始化IoC容器(Spring源码阅读)
初始化IoC容器(Spring源码阅读) 我们到底能走多远系列(31) 扯淡: 有个问题一直想问:各位你们的工资剩下来会怎么处理?已婚的,我知道工资永远都是不够的.未婚的你们,你们是怎么分配工资的? ...
- Spring事务源码阅读笔记
1. 背景 本文主要介绍Spring声明式事务的实现原理及源码.对一些工作中的案例与事务源码中的参数进行总结. 2. 基本概念 2.1 基本名词解释 名词 概念 PlatformTransaction ...
随机推荐
- (转)python 搭建libsvm方法。python版本和libsvm版本匹配很重要!
<集体智慧编程>关于婚介数据集的SVM分类 转自:http://muilpin.blog.163.com/blog/static/165382936201131875249123/ 作 ...
- [洛谷P4171][JSOI2010]满汉全席
题目大意:有$n$个点,每个点可以选或不选,有$m$组约束,形如$a,u,b,v$,表示$u=a,v=b$中至少要满足一个条件,问是否存在一组解,多组询问 题解:$2-SAT$,感觉是板子题呀,最后判 ...
- CF311B Cats Transport 斜率优化DP
题面:CF311B Cats Transport 题解: 首先我们观察到山与距离其实是没有什么用的,因为对于任意一只猫,我们都可以直接算出如果有一个人要恰好接走它,需要在哪一时刻出发,我们设第i只猫对 ...
- POJ3090:Visible Lattice Points——题解
http://poj.org/problem?id=3090 题目大意:你站在(0,0)的点上看向第一向限的点,点和点会互相阻挡,问最多看到多少点. 很容易想到,我们能看到的点,它的横纵坐标一定是互质 ...
- BZOJ5339:[TJOI2018]教科书般的亵渎——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=5339 https://www.luogu.org/problemnew/show/P4593 小豆 ...
- 斜率优化第一题! HDU3507 | 单调队列优化DP
放一手原题 题解: 第一次写(抄)斜率优化,心里还是有点小激动的.讲一下怎么实现的! 首先我们可以考虑一个朴素的dp:DP[i]表示前i个数字的最少花费,显然我们有一个转移方程 DP[i]=min{D ...
- Linux上安装Oracle11g
1.首先是挂盘 1.1 Linux硬盘挂载步骤:查看磁盘 先查看目前机器上有几块硬盘,查看命令有两种: 命令1:# fdisk –l 命令2:# dmesg | grep sd 其中:fdisk命令说 ...
- [POI2014]DOO-Around the world
通过几年的努力,Byteasar最终拿到了飞行员驾驶证.为了庆祝这一事实,他打算买一架飞机并且绕Byteotia星球赤道飞行一圈.但不幸的是赤道非常长所以需要中途加几次油.现在已知赤道上面所有飞机场, ...
- 四连测Day2
题目:链接: https://pan.baidu.com/s/1ef_9hGBhczW0B4dz5IUKmw 密码: qgjy T1: hash后直接二分查询即可 #include<iostre ...
- 一篇博文将JavaScript尽收眼底
简介 这篇文章是为专业程序员介绍的JavaScript语言的,它是一种小巧的语言,如果你熟悉其他的编程语言,那么这篇文章对你来讲不是那么难以理解. JavaScript不是Java,他们是两门完全不同 ...