从上图可能看出,在 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类的更多相关文章

  1. 精尽MyBatis源码分析 - MyBatis-Spring 源码分析

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  2. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  3. MyBatis源码分析(5)——内置DataSource实现

    @(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...

  4. MyBatis源码分析(4)—— Cache构建以及应用

    @(MyBatis)[Cache] MyBatis源码分析--Cache构建以及应用 SqlSession使用缓存流程 如果开启了二级缓存,而Executor会使用CachingExecutor来装饰 ...

  5. MyBatis源码分析(3)—— Cache接口以及实现

    @(MyBatis)[Cache] MyBatis源码分析--Cache接口以及实现 Cache接口 MyBatis中的Cache以SPI实现,给需要集成其它Cache或者自定义Cache提供了接口. ...

  6. MyBatis源码分析(2)—— Plugin原理

    @(MyBatis)[Plugin] MyBatis源码分析--Plugin原理 Plugin原理 Plugin的实现采用了Java的动态代理,应用了责任链设计模式 InterceptorChain ...

  7. 【MyBatis源码分析】select源码分析及小结

    示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是 ...

  8. MyBatis源码分析之环境准备篇

    前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的 ...

  9. Mybatis源码分析-BaseExecutor

    根据前文Mybatis源码分析-SqlSessionTemplate的简单分析,对于SqlSession的CURD操作都需要经过Executor接口的update/query方法,本文将分析下Base ...

随机推荐

  1. 关于ligerUI中ligerTree代码中的一个bug,造成该控件无法通过url的POST方式加载数据

    该bug造成ligerTree参数中的method无论你怎么设置都只能用get方式提交 由于本人水平有限,只是找到原因,但无法修正 ligerUI v1.1.9 版本中的ligerui.all.js文 ...

  2. PHP和MYSQL的编码问题

    http://blog.csdn.net/martinkro/article/details/5352474 1 MYSQL中的字符集概念  Mysql的字符集里有两个概念,一个是"Char ...

  3. CSS3 transition-timing-function

    CSS3 transition-timing-function 属性 定义和用法 transition-timing-function 属性规定过渡效果的速度曲线. 该属性允许过渡效果随着时间来改变其 ...

  4. O-C相关-08-动态类型与静态类型

    08-动态类型与静态类型 1, 什么是动态类型和静态类型 1) 动态语言 又叫动态编程语言,是指程序在运行时可以改变其结构:新的函数可以被引进,已有的函数可以被删除等在结构上的变化.比如众所周知的EC ...

  5. webstorm 快捷键

    Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*-*/ ) Shift+F6 重构-重命名 Ctrl+X 删除行 Ctrl+D 复制行 Ctrl+G 查找行 Ctrl+Shift+Up ...

  6. javascript DOM操作 第19节

    <html> <head> <title>DOM对象</title> <script type="text/javascript&quo ...

  7. struts2 I18n问题 国际化

    java国际化 1.了解缺省Locale是由操作系统决定的,Locale是由语言和国家代码组成 2.国际化资源文件是由baseName+locale组成,如:MessageBundle_en_US.p ...

  8. 九度OJ 1066 字符串排序

    题目地址:http://ac.jobdu.com/problem.php?pid=1066 题目描述: 输入一个长度不超过20的字符串,对所输入的字符串,按照ASCII码的大小从小到大进行排序,请输出 ...

  9. wampserver下升级php7

    1.下载php7   http://windows.php.net/download#php-7.0 选择 VC14 x86 Thread Safe  64位选X64 32位选X86 2.下载VC14 ...

  10. PHP实现多web服务器共享SESSION数据-session数据写入mysql数据库

    http://www.php100.com/html/webkaifa/PHP/PHPyingyong/2010/0822/5276.html http://hi.baidu.com/lei_com/ ...