文档章节

mybatis中Mapper接口如何实例化的

梦蝶飘雪
 梦蝶飘雪
发布于 2017/02/16 16:35
字数 844
阅读 70
收藏 0
点赞 0
评论 0

关于mybatis的一个疑惑(Mapper接口如何实例化的),有需要的朋友可以参考下。

 

今天早上有个疑惑,在mybatis+SpringMVC的工程中,我只定义了一个接口UserMapper,而Spring就产生了一个UserMapper的对象,这个是我所不明白的,一个接口如何实例化。查了一下,发现Java 动态代理机制分析及扩展,估计mybatis也是这样实现的。看了看mybatis的源码,就有下文了。

 

本文主要跟踪mybatis的源码,了解mapper接口的动态代理对象的生成

 

mybatis的部分Spring配置文件如下,跟踪其中id=”userMapper”的bean是如何创建的

 

    <!-- mybatis配置 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation" value="classpath:sqlMapConfig.xml" />
</bean>
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
        <property name="mapperInterface" value="com.tqd.dao.UserMapper"></property>
        <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

 

此处是通过工厂方法创建Bean 
首先我们定位到类 org.mybatis.spring.mapper.MapperFactoryBean

 

public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements
        FactoryBean<T> {
    private Class<T> mapperInterface;
    private boolean addToConfig;

 

可以看到该类实现了org.springframework.beans.factory.FactoryBean接口,通过调用 
org.mybatis.spring.mapper.MapperFactoryBean.getObject()方法来获得Bean

 


    public T getObject() throws Exception {
        return getSqlSession().getMapper(this.mapperInterface);
    }

 

从这个方法中,可以看到先调用了其父类SqlSessionDaoSupport 的getSqlSession()方法,然后返回一个SqlSession对象,再调用这个对象的getMapper方法

 

    public SqlSession getSqlSession() {
        return this.sqlSession;
    }

 

在这个方法中直接返回陪父类成员变量sqlSession,sqlSession是一个接口SqlSession的对象,要找到它的实现类。在类SqlSessionDaoSupport 的代码中

 

public abstract class SqlSessionDaoSupport extends DaoSupport {
    private SqlSession sqlSession;
    private boolean externalSqlSession;

public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
        if (!(this.externalSqlSession))
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
    }

public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSession = sqlSessionTemplate;
        this.externalSqlSession = true;
    }

public SqlSession getSqlSession() {
        return this.sqlSession;
    }

protected void checkDaoConfig() {
        Assert.notNull(this.sqlSession,
                "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
    }
}

 

我们可以找到两个方法,它们当中都包含了sqlSession的实例化代码

 

public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {

        if (!(this.externalSqlSession))
            this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}

public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
        this.sqlSession = sqlSessionTemplate;
        this.externalSqlSession = true;
}

 

根据bean的配置文件

 

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
    <property name="mapperInterface" value="com.tqd.dao.UserMapper"></property>
    <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

 

Spring要将属性sqlSessionFactory注入到MapperFactoryBean的对象中,那么会调用setSqlSessionFactory方法,然后sqlSession 就被实例化。我们此时肯定知道 
sqlSession的实现类是org.mybatis.spring.SqlSessionTemplate,我们定位到它的getMapper方法。

 

    public <T> T getMapper(Class<T> type) {
        return getConfiguration().getMapper(type, this);
    }

 

可以看到,它首先调用了自身的getConfiguration()方法返回一个Configuration对象,然后再调用Configuration对象的getMapper方法

 

    public Configuration getConfiguration() {
        return this.sqlSessionFactory.getConfiguration();
    }

 

我们直接定位到Configuration的getMapper方法

 

  public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    return mapperRegistry.getMapper(type, sqlSession);
  }

 

可以看到,在这里调用了对象mapperRegistry的getMapper方法,直接定位到该方法

 

@SuppressWarnings("unchecked")
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
    final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
    if (mapperProxyFactory == null)
      throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
    try {
      return mapperProxyFactory.newInstance(sqlSession);
    } catch (Exception e) {
      throw new BindingException("Error getting mapper instance. Cause: " + e, e);
    }
  }

 

在这个方法里,首先获得一个MapperProxyFactory的对象mapperProxyFactory,然后调用该对象的newInstance方法创建我们需要的bean,定位到newInstance方法

 

public T newInstance(SqlSession sqlSession) {
    final MapperProxy<T> mapperProxy = new MapperProxy<T>(sqlSession, mapperInterface, methodCache);
    return newInstance(mapperProxy);
  }

 

在这里,首先构造出一个MapperProxy对象,然后调用自身的newInstance(重载的另一个方法)方法。

 

@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

 

Bean最终在这里创建的。关于这里推荐大家去看下Java 动态代理机制分析及扩展

本文转载自:http://www.aichengxu.com/java/68780.htm

共有 人打赏支持
梦蝶飘雪
粉丝 4
博文 26
码字总数 7682
作品 0
东城
程序员
spring中的mybatis(1)

开门见山 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="cl......

hyssop
2015/10/29
0
0
Mybatis学习系列(七)缓存机制

Mybatis缓存介绍 MyBatis提供一级缓存和二级缓存机制。 一级缓存是Sqlsession级别的缓存,Sqlsession类的实例对象中有一个hashmap用于缓存数据。不同的Sqlsession实例直接hashmap互不影响。M...

仍是少年
07/12
0
0
就是让你懂Spring中Mybatis的花样配置

一、前言 Mybatis作为一个优秀的存储过程和高级映射的持久层框架,目前在项目实践中运用的比较广泛,最近做项目时候发现了一种之前没见过的配置方式,这里总结下常用的配置方式以便备忘查找。...

今天你不奋斗明天你就落后
2017/09/03
0
0
Mybatis3.3.x技术内幕(二):动态代理之投鞭断流(自动映射器Mapper的底层实现原理)

一日小区漫步,我问朋友:Mybatis中声明一个interface接口,没有编写任何实现类,Mybatis就能返回接口实例,并调用接口方法返回数据库数据,你知道为什么不?朋友很是诧异:是啊,我也很纳闷...

祖大俊
2016/04/26
2.4K
12
Mybatis-spring整合源码解析

原文:http://my.oschina.net/doctor2014/blog/411594 Mybatis整合spring,主要通过两种途径:一种是基于xml配置的,一种基于java config 配置。 一种是基于xml配置的。这种方式通过解析xml...

Beaver_
2015/05/07
1K
0
mybatis(六)objectFactory、plugins、mappers简介与配置

上篇文章简单看了一下TypeHandler, 本次将结束对于mybatis的配置文件的学习, 本次涉及到剩下没提及到的几个节点的配置:objectFactory、databaseIdProvider、plugins、mappers。 那么,接下...

LCZ777
2014/12/19
0
0
MyBatis接口(Bean)与配置信息(Mapper)绑定

目的 MyBatis的XML配置文件解析成JAVA类并在内存中存储,但是在程序运行时需要对应的类去调用,而相应的调用类还没有实例化,现在流行的都是使用Spring去管理需要的对象,Spring提供2种方式,...

tara_qri
2015/10/31
0
0
Mybatis spring and mybatis and mybatis-springboot-starter

Mybatis spring and mybatis and mybatis-springboot-starter 这篇博文主要涉及到的是mybatis是怎么集成到spring已经spring boot的,有关mybatis的用法及其自身的源码 设计,我会到开另一个文...

来福马斯特
04/25
0
0
Mybatis源码概览(二) ---Plugin扩展与Spring结合原理

本文主要介绍Mybatis通过动态代理避免对sqlSession直接调用,而是通过MapperProxy代理技术生成了具体dao接口的Mapper实例,里面封装了对sqlSession的调用;Mybatis预留了Interceptor接口,用...

robin-yao
2016/03/23
530
0
mybatis--总结

1.mybatis简介 mybatis是一个基于java的持久层框架,支持普通sql查询/存储过程/对象映射,它使用xml配置或者注解配置来做映射,将普通java对象映射到数据库中。 2.mybatis功能分层 2.1api接口...

求是科技
2016/10/12
26
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android 复制和粘贴功能

做了一回搬运工,原文地址:https://blog.csdn.net/kennethyo/article/details/76602765 Android 复制和粘贴功能,需要调用系统服务ClipboardManager来实现。 ClipboardManager mClipboardM...

她叫我小渝
今天
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
今天
6
0
jQuery零基础入门——(六)修改DOM结构

《jQuery零基础入门》系列博文是在廖雪峰老师的博文基础上,可能补充了个人的理解和日常遇到的点,用我的理解表述出来,主干出处来自廖雪峰老师的技术分享。 在《零基础入门JavaScript》的时...

JandenMa
今天
0
0
linux mint 1.9 qq 安装

转: https://www.jianshu.com/p/cdc3d03c144d 1. 下载 qq 轻聊版,可在百度搜索后下载 QQ7.9Light.exe 2. 去wine的官网(https://wiki.winehq.org/Ubuntu) 安装 wine . 提醒网页可以切换成中...

Canaan_
今天
0
0
PHP后台运行命令并管理运行程序

php后台运行命令并管理后台运行程序 class ProcessModel{ private $pid; private $command; private $resultToFile = ''; public function __construct($cl=false){......

colin_86
今天
1
0
数据结构与算法4

在此程序中,HighArray类中的find()方法用数据项的值作为参数传递,它的返回值决定是否找到此数据项。 insert()方法向数组下一个空位置放置一个新的数据项。一个名为nElems的字段跟踪记录着...

沉迷于编程的小菜菜
今天
1
1
fiddler安装和基本使用以及代理设置

项目需求 由于开发过程中客户端和服务器数据交互非常频繁,有时候服务端需要知道客户端调用接口传了哪些参数过来,这个时候就需要一个工具可以监听这些接口请求参数,已经接口的响应的数据,这种...

银装素裹
今天
0
0
Python分析《我不是药神》豆瓣评论

读取 Mongo 中的短评数据,进行中文分词 对分词结果取 Top50 生成词云 生成词云效果 看来网上关于 我不是药神 vs 达拉斯 的争论很热啊。关于词频统计就这些,代码中也会完成一些其它的分析任...

猫咪编程
今天
0
0
虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
昨天
1
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部