mybatis源码分析(3)——SqlSessionManager类
从上图可能看出,在 mybatis中,SqlSession的实现类有两个,其中SqlSessionManager类不但实现了SqlSession接口,同时也实现了SqlSessionFactory接口。那么SqlSessionManager类究竟有何作用 ? 由于源码中缺少注释,所以从mybatis目前的提供官方文档来看,似乎该类已被弃用,其功能被DefaultSqlSession类和DefaultSqlSessionFactory类所代替。只是该类的部分代码对我们理解mybatis的一些底层机制还具有一定的参考价值,例如:
SqlSessionManager的下面的构造方法,会产生一个SqlSession的一个代理对象:
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {
this.sqlSessionFactory = sqlSessionFactory;
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSession.class},
new SqlSessionInterceptor());
}
SqlSessionInterceptor类实现了InvocationHandler接口
privaprivate class SqlSessionInterceptor implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();
if (sqlSession != null) {
try {
return method.invoke(sqlSession, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} else {
final SqlSession autoSqlSession = openSession();
try {
final Object result = method.invoke(autoSqlSession, args);
autoSqlSession.commit();
return result;
} catch (Throwable t) {
autoSqlSession.rollback();
throw ExceptionUtil.unwrapThrowable(t);
} finally {
autoSqlSession.close();
}
}
}
}
private class SqlSessionInterceptor implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();
if (sqlSession != null) {
try {
return method.invoke(sqlSession, args);
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
} else {
final SqlSession autoSqlSession = openSession();
try {
final Object result = method.invoke(autoSqlSession, args);
autoSqlSession.commit();
return result;
} catch (Throwable t) {
autoSqlSession.rollback();
throw ExceptionUtil.unwrapThrowable(t);
} finally {
autoSqlSession.close();
}
}
}
}
下面对这一段使用JAVA动态代理技术产生SqlSession代理对象的代码进行分析:
this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(
SqlSessionFactory.class.getClassLoader(),
new Class[]{SqlSession.class},
new SqlSessionInterceptor()) 这句是关键,JDK的Proxy类的newProxyInstance方法的方法原型如下:
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
在调这个方法中需要传入三个参数:
Ø 一个interfaces的数组参数
Ø 一个InvocationHanler 接口的实例对象
Ø 一个类加载器,
则Proxy.newProxyInstance方法执行后会返回interfaces中任一接口的实例对象(假设该对象为proxyObject),那么当我们在调用这个对象proxyObject的相应方法时,就会进入到InvocationHandler 这个参数对象的invoke(Object proxy, Method method, Object[] args)方法中,或者换句话说,就会被h这个对象的invoke方法拦截, 对象proxyObject会作为
Invoke中的proxy参数,proxyObject调用的方法的方法对象会作为method参数,方法的参数会作为args参数,这样在InvocationHandler 对象的invoke方法中,就会通过Method.invoke方法来执行具体的目标对象的相应方法,在mybatis的这个应用场景上,这个目标对象其实就是一个SqlSession的实例,通过SqlSessionManager类的成员变量sqlSessionFactory的openSession()获得或者从当前线程中获取。
以上的实现技术主要就是使用了java的动态代理技术,看到网上不少人在问这个InvocationHandler 接口中的invoke方法的第一个参数proxy究竟有何作用,这个proxy其实就是一个代理对象实例(通过Proxy.newProxyInstance方法产生),下面就举例说明一下它的作用:
可参照 java.rmi.server.RemoteObjectInvocationHandler类中的相应方法invoke方法,一个用法就是判断invoke的method参数,看是否有必要调用proxy对象的其他方法,另一个用处就是作为参数把该对象提供给远程调用的方法使用。
mybatis源码分析(3)——SqlSessionManager类的更多相关文章
- 精尽MyBatis源码分析 - MyBatis-Spring 源码分析
该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...
- MyBatis源码分析-SQL语句执行的完整流程
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...
- MyBatis源码分析(5)——内置DataSource实现
@(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...
- MyBatis源码分析(4)—— Cache构建以及应用
@(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...
- MyBatis源码分析(3)—— Cache接口以及实现
@(MyBatis)[Cache] MyBatis源码分析--Cache接口以及实现 Cache接口 MyBatis中的Cache以SPI实现,给需要集成其它Cache或者自定义Cache提供了接口. ...
- MyBatis源码分析(2)—— Plugin原理
@(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...
- 【MyBatis源码分析】select源码分析及小结
示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...
- MyBatis源码分析之环境准备篇
前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...
- Mybatis源码分析-BaseExecutor
根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...
随机推荐
- c#简体繁体转换
方法一已经亲测,使用正常,方法二貌似不能用. 方法一 /// <summary> /// 中文字符工具类 /// </summary> public static class ...
- C#中2、8、16进制 有符号转换10进制正负数
曾经让我苦想的其他进制转有符号整型问题,结果自己想到方法解决后才发现原来如此简单. 1.Int16(2个byte长度 ) : 方法 :Convert.ToInt16(进制编码,进制) a.16进制转1 ...
- js使用正则表达式去空格
写成类的方法格式如下:(str.trim();) <script language="javascript"> String.prototype.trim=functi ...
- 10.20_wiki
XWiki:官网.Documentation.User's GuideProgrammer's GuideAdministrator's Guide Developer's Guide (1) htt ...
- CentOS7设置IP地址
root权限下cd到/etc/sysconfig/network-scripts, vi ifcig-em1 TYPE=Ethernet BOOTPROTP=static NAME=em1 UUID= ...
- Demo_张仕传_结构体考试-modify
/* 题目: //声明一个结构体类型 struct _AdvTeacher { char *name; char *tile; int age; char *addr; char *p1; //系统预 ...
- 安装会声会影x8后打不开的解决方法
操作系统:Windows 7 症状:双击程序图标后一直停留在购买介绍页,主程序界面一直无法打开 解决方法:删除系统补丁KB3126587和KB3126593
- SQL 添加字段和默认值脚本
--插入字段和默认值alter table Acc_WayBill add DeclaredValue nvarchar(50)goEXEC sys.sp_addextendedproperty @n ...
- C#事件作用和用法
例如有下面的需求需要实现:程序主画面中弹出一个子窗口.此时主画面仍然可以接收用户的操作(子窗口是非模态的).子窗口上进行某些操作,根据操作的结果要在主画面上显示不同的数据. 即如下图所示: 大多数我们 ...
- js异步脚本
1.延迟脚本 HTML4.01为<script>标签定义了defer属性,为了表明脚本在执行时不会影响页面的构造.也就是说,脚本会在整个页面都解析完毕后再运行.因此在<script& ...