Mybatis接口编程原理分析(一)
Mybatis接口编程示例
(1)首先定义接口编程需要的接口及其方法
public interface IUserMapper { public User getById(int id);//接口方法,不需要实现 }
(2)创建mybatis的mapper文件,其中namespace的值为接口的完整类名
<mapper namespace="com.tianjunwei.learn.learn2.IUserMapper">//接口完整类名 <select id="getById" parameterType="int" resultType="com.tianjunwei.learn.learn1.entity.User"> select * from users where id=#{id} </select> </mapper>
(3)创建接口调用操作
public class Learn2Main { public static void main(String [] args){ String resource = "learn/mybatis-config.xml"; InputStream is = Learn1Main.class.getClassLoader().getResourceAsStream(resource); SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is); SqlSession session = sessionFactory.openSession(); IUserMapper userMapper = session.getMapper(IUserMapper.class);//获取接口,已经是代理接口 userMapper.getById(1); RowBounds rowBounds = new RowBounds(2, 4);//接口分页编程 System.out.println(userMapper.page(rowBounds).size()); } }
Mybatis接口编程相关的类主要有MapperProxyFactory、MapperProxy、MapperMethod和MapperRegister四个类:
MapperProxyFactory:通过类名我们可以猜到这是一个MapperProxy的工厂类,用于创建MapperProxy的,通过函数newInstance(SqlSession sqlSession)来创建MapperProxy的代理类。
源码如下:
//这个类赋值创建具体mapper接口代理对象的工厂 public class MapperProxyFactory<T> { //具体Mapper接口的class对象 private final Class<T> mapperInterface; //该接口下面的缓存,key是方法对象,value是对接口中方法对象的封装 private final Map<Method, MapperMethod> methodCache = new ConcurrentHashMap<Method, MapperMethod>(); public MapperProxyFactory(Class<T> mapperInterface) { this.mapperInterface = mapperInterface; } public Class<T> getMapperInterface() { return mapperInterface; } public Map<Method, MapperMethod> getMethodCache() { return methodCache; } @SuppressWarnings("unchecked") protected T newInstance(MapperProxy<T> mapperProxy) { //创建一个代理类并返回 return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy); } public T newInstance(SqlSession sqlSession) { //在这里创建MapperProxy对象,这个类实现了JDK的动态代理接口 InvocationHandler final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache); //调用上面的方法,返回一个接口的代理类 return newInstance(mapperProxy); } }
MapperProxy:通过类名可以猜到这个类为一个代理类,它实现了JDK动态代理接口InvocationHandler,通过查看源码发现它又不像一个真正的代理类,它一般不会真正执行被代理类的函数方法,只是在执行被代理类函数方法时来执行MapperMethod类的execute方法,具体逻辑详看invoke函数
源码如下:
//实现了JDK动态代理的接口,InvocationHandler //在invoke方法中实现了代理方法调用的细节 public class MapperProxy<T> implements InvocationHandler, Serializable { private static final long serialVersionUID = -6424540398559729838L; //sqlSession private final SqlSession sqlSession; //接口的类型对象 private final Class<T> mapperInterface; //接口中方法的缓存,由MapperProxyFactory传递过来 private final Map<Method, MapperMethod> methodCache; //构造函数 public MapperProxy(SqlSession sqlSession, Class<T> mapperInterface, Map<Method, MapperMethod> methodCache) { this.sqlSession = sqlSession; this.mapperInterface = mapperInterface; this.methodCache = methodCache; } //接口代理对象所有的方法调用都会调用该方法 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //判断是不是基础方法比如toString、hashCode等,这些方法直接调用不需要处理 if (Object.class.equals(method.getDeclaringClass())) { try { return method.invoke(this, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } //进行缓存 final MapperMethod mapperMethod = cachedMapperMethod(method); //调用mapperMethod.execute 核心的地方就在这个方法里,这个方法对才是真正对SqlSession进行的包装调用 return mapperMethod.execute(sqlSession, args); } //缓存处理 private MapperMethod cachedMapperMethod(Method method) { MapperMethod mapperMethod = methodCache.get(method); if (mapperMethod == null) { mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()); methodCache.put(method, mapperMethod); } return mapperMethod; } }
Mybatis接口编程原理分析(一)的更多相关文章
- Mybatis接口编程原理分析(三)
前面两篇博客Mybatis接口编程原理分析(一)和Mybatis接口编程原理分析(二)我们介绍了MapperProxyFactory.MapperProxy和MapperMethod的操作及源码分析, ...
- Mybatis接口编程原理分析(二)
在上一篇博客中 Mybatis接口编程原理分析(一)中我们介绍了MapperProxyFactory和MapperProxy,接下来我们要介绍的是MapperMethod MapperMethod:它 ...
- MyBatis整合Spring原理分析
目录 MyBatis整合Spring原理分析 MapperScan的秘密 简单总结 假如不结合Spring框架,我们使用MyBatis时的一个典型使用方式如下: public class UserDa ...
- MyBatis的深入原理分析之1-架构设计以及实例分析
MyBatis是目前非常流行的ORM框架,它的功能很强大,然而其实现却比较简单.优雅.本文主要讲述MyBatis的架构设计思路,并且讨论MyBatis的几个核心部件,然后结合一个select查询实例, ...
- MyBatis框架及原理分析
MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 MyBatis的主要设计目的就 ...
- Linux下Golang Socket编程原理分析与代码实现
在POSIX标准推出后,socket在各大主流OS平台上都得到了很好的支持.而Golang是自带Runtime的跨平台编程语言,Go中提供给开发者的Socket API是建立在操作系统原生Socket ...
- Mybatis插件原理分析(三)分页插件
在Mybatis中插件最经常使用的是作为分页插件,接下来我们通过实现Interceptor来完成一个分页插件. 虽然Mybatis也提供了分页操作,通过在sqlSession的接口函数中设置RowBo ...
- mybatis(一、原理,一对多,多对一查询)
MyBatis框架及原理分析 MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架,其主要就完成2件事情: 封装JDBC操作 利用反射打通Java类与SQL语句之间的相互转换 ...
- Spark原理分析目录
1 Spark原理分析 -- RDD的Partitioner原理分析 2 Spark原理分析 -- RDD的shuffle简介 3 Spark原理分析 -- RDD的shuffle框架的实现概要分析 ...
随机推荐
- day06_JDBC学习笔记
============================================================ 一.JDBC概述 为什么要使用JDBC? JDBC:Java DataBase ...
- 更快实现Android多级树形选择列表
快速实现Android多级树形列表,这个库是在鸿洋多级树形列表demo中修改而来. 解决的问题: 1. 支持ID为int类型和String类型. 2. 支持多级复选框选中,使用只需一行代码. 3. 支 ...
- ThreadLocal(线程绑定)
为保证在DAO层里的操作都在同一事务里,我们曾使用以参数的形式将Connection向下传递的方式,而ThreadLocal来创建Connection连接,避免了一直以参数的形式将Connection ...
- Scala:函数式编程之下划线underscore
http://blog.csdn.net/pipisorry/article/details/52913548 python参考[python函数式编程:apply, map, lambda和偏函数] ...
- ELK搭建
ELK安装 elasticsearch安装 * 下载elasticsearch-5.0.0.tar.gz,并解压. 通过elasticsearch.yml可设置host和port. vim confi ...
- [Pelican]Pelican入门(一)
听说这个静态博客很好用,最近又在协助"蟒周刊"翻译,于是先学习下基本的用法 office site You can startup for here. 安装环境 我的os是win7 ...
- java.util.Arrays类详解(源码总结)
概述 Arrays类位于java.util包下,是一个对数组操作的工具类.今天详细的看了看Arrays类的4千多行源码,现将Arrays类中的方法做一个总结(JDK版本:1.6.0_34).Array ...
- Swift基础语法(常量变量、数据类型、元组、可选、断言)
本文来自Swift中文开发组,感谢翻译者的分享. 本文将分几部分对Swift对ios的语法做讲解.本文为第一节,主要讲解基础语法. 常量和变量 常量和变量把一个名字(比如maximumNumberOf ...
- JQuery其他常用函数
isArray(obj) 检测obj否为一个数组对象 isFunction(obj) 检测obj否为一个函数 isEmptyO ...
- Cocos2D在Xcode7和iOS 9.2上IMP调用出错
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 原来的代码一直在Xcode6.4上和iOS 8.4上运行,没有 ...