Spring整合MyBatis(四)MapperFactoryBean 的创建
摘要: 本文结合《Spring源码深度解析》来分析Spring 5.0.6版本的源代码。若有描述错误之处,欢迎指正。
目录
一、MapperFactoryBean的初始化
二、获取 MapperFactoryBean 的实例
为了使用MyBatis功能,示例中的Spring配置文件提供了两个bean,除了之前分析的 SqlSessionFactoryBean 类型的 bean 以外,还有一个是 MapperFactoryBean 类型的 bean。
结合两个测试用例综合分析,对于单独使用MyBatis的时候调用数据库接口的方式是:
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
而在这一过程中,其实是MyBatis在获取映射的过程中根据配置信息为UserMapper类型动态创建了代理类。而对于Spring的创建方式:
UserMapper userMapper = (UserMapper) context.getBean("userMapper");
Spring中获取的名为userMapper的bean,其实是与单独使用MyBatis完成了—样的功能,那么我们可以推断,在bean的创建过程中一定是使用了MyBatis中的原生方法sqlSession.getMapper(UserMapper.class)进行了再一次封装。结合配置文件,我们把分析目标转向org.mybatis.spring.mapper.MapperFactoryBean,初步推测其中的逻辑应该在此类中实现。同样,还是首先查看的类层次结构图MapperFactoryBean,如下图所示。
同样,在实现的接口中发现了我们感兴趣的两个接口InitializingBean与FactoryBean。我们的分析还是从bean的初始化开始。
一、MapperFactoryBean的初始化
因为实现了InitializingBean接口,Spring会保证在bean初始化时首先调用afterPropertiesSet方法来完成其初始化逻辑。追踪父类,发现afterPropertiesSet方法是在DaoSupport类中实现,代码如下:
@Override
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException {
// Let abstract subclasses check their configuration.
checkDaoConfig(); // Let concrete implementations initialize themselves.
try {
initDao();
}
catch (Exception ex) {
throw new BeanInitializationException("Initialization of DAO failed", ex);
}
}
但从函数名称来看我们大体推测,MapperFactoryBean的初始化包括对DAO配置的验证以及对DAO的初始工作,其中initDao()方法是模板方法,设计为留给子类做进一步逻辑处理。而checkDaoConfig()才是我们分析的重点。
@Override
protected void checkDaoConfig() {
super.checkDaoConfig(); notNull(this.mapperInterface, "Property 'mapperInterface' is required"); Configuration configuration = getSqlSession().getConfiguration();
if (this.addToConfig && !configuration.hasMapper(this.mapperInterface)) {
try {
configuration.addMapper(this.mapperInterface);
} catch (Exception e) {
logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e);
throw new IllegalArgumentException(e);
} finally {
ErrorContext.instance().reset();
}
}
}
super.checkDaoConfig()在SqlSessionDaoSupport类中实现,代码如下:
@Override
protected void checkDaoConfig() {
notNull(this.sqlSessionTemplate, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
结合代码我们了解到对于DAO配置的验证,Spring做了以下几个方面的工作。
- 父类中对于sqlSession不为空的验证。
sqlSession作为根据接口创建映射器代理的接触类一定不可以为空,而sqlSession的初始化工作是在设定其sqlSessionFactory属性时完成的。
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (this.sqlSessionTemplate == null || sqlSessionFactory != this.sqlSessionTemplate.getSqlSessionFactory()) {
this.sqlSessionTemplate = createSqlSessionTemplate(sqlSessionFactory);
}
}
也就是说,对于下面的配置如果忽略了对于sqlSessionFactoiy属性的设置,那么在此时就会被检测出来。
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="org.cellphone.uc.repo.mapper.UserMapper"/>
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
- 映射接口的验证。
接口是映射器的基础,sqlSession会根据接口动态创建相应的代理类,所以接口必不可少。
- 映射文件存在性验证。
对于函数前半部分的验证我们都很容易理解,无非是对配置文件中的属性是否存在做验证,但是后面部分是完成了什么方面的验证呢?如果读者读过MyBatis源码,你就会知道,在MyBatis实现过程中并没有手动调用configuration.addMapper方法,而是在映射文件读取过程中一旦解析到如<mapper namespace="org.cellphone.uc.repo.mapper.UserMapper">,便会自动进行类型映射的注册。那么,Spring中为什么会把这个功能单独拿出来放在验证里呢?这是不是多此一举呢?
在上面的函数中,configuration.addMapper(this.mapperInterface)其实就是将 UserMapper 注册到映射类型中,如果你可以保证这个接口一定存在对应的映射文件,那么其实这个验证并没有必要。但是,由于这个是我们自行决定的配置,无法保证这里配罝的接口一定存在对应的映射文件,所以这里非常有必要进行验证。在执行此代码的时候,MyBatis会检査嵌人的映射接口是否存在对应的映射文件,如果没有回抛出异常,Spring正是在用这种方式来完成接口对应的映射文件存在性验证。
二、获取 MapperFactoryBean 的实例
由于MapperFactoryBean实现了FactoryBean接口,所以当通过getBean方法获取对应实例的时候其实是获取该类的getObject()函数返回的实例。
@Override
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
这段代码正是我们在提供MyBatis独立使用的时候的一个代码调用。Spring通过 FactoryBean 进行了封装。
Spring整合MyBatis(四)MapperFactoryBean 的创建的更多相关文章
- spring基础:什么是框架,框架优势,spring优势,耦合内聚,什么是Ioc,IOC配置,set注入,第三方资源配置,综合案例spring整合mybatis实现
知识点梳理 课堂讲义 1)Spring简介 1.1)什么是框架 源自于建筑学,隶属土木工程,后发展到软件工程领域 软件工程中框架的特点: 经过验证 具有一定功能 半成品 1.2)框架的优势 提高开发效 ...
- Java开发学习(十四)----Spring整合Mybatis及Junit
一.Spring整合Mybatis思路分析 1.1 环境准备 步骤1:准备数据库表 Mybatis是来操作数据库表,所以先创建一个数据库及表 create database spring_db cha ...
- Spring整合MyBatis(三)sqlSessionFactory创建
摘要: 本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 目录 一.SqlSessionFactoryBean的初始化 二.获取 ...
- Mybatis学习(六)————— Spring整合mybatis
一.Spring整合mybatis思路 非常简单,这里先回顾一下mybatis最基础的根基, mybatis,有两个配置文件 全局配置文件SqlMapConfig.xml(配置数据源,全局变量,加载映 ...
- Mybatis(六) Spring整合mybatis
心莫浮躁~踏踏实实走,一步一个脚印,就算不学习,玩,能干嘛呢?人生就是那样,要找点有意思,打发时间的事情来做,而钻研技术,动脑动手的过程,还是比其他工作更有意思些~ so,努力啥的都是强迫自己做自以为 ...
- Spring学习总结(六)——Spring整合MyBatis完整示例
为了梳理前面学习的内容<Spring整合MyBatis(Maven+MySQL)一>与<Spring整合MyBatis(Maven+MySQL)二>,做一个完整的示例完成一个简 ...
- Spring学习总结(五)——Spring整合MyBatis(Maven+MySQL)二
接着上一篇博客<Spring整合MyBatis(Maven+MySQL)一>继续. Spring的开放性和扩张性在J2EE应用领域得到了充分的证明,与其他优秀框架无缝的集成是Spring最 ...
- 深入源码理解Spring整合MyBatis原理
写在前面 聊一聊MyBatis的核心概念.Spring相关的核心内容,主要结合源码理解Spring是如何整合MyBatis的.(结合右侧目录了解吧) MyBatis相关核心概念粗略回顾 SqlSess ...
- 分析下为什么spring 整合mybatis后为啥用不上session缓存
因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...
- 2017年2月16日 分析下为什么spring 整合mybatis后为啥用不上session缓存
因为一直用spring整合了mybatis,所以很少用到mybatis的session缓存. 习惯是本地缓存自己用map写或者引入第三方的本地缓存框架ehcache,Guava 所以提出来纠结下 实验 ...
随机推荐
- 客户端ajax请求为实现Token验证添加headers后导致正常请求变为options跨域请求解决方法
客户端为了实现token认证,通过Jquery的ajaxSetup方法全局配置headers: 全局配置headers后会导致部分不需要token认证的请求变为options请求,导致跨域访问.报错信 ...
- js实现放大镜的效果
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- Vue 实现复制到粘贴板功能
vue 实现复制到粘贴板功能需要依赖到 clipboard.js 1. 首先需要安装依赖 * 出现错误的话,可以试试 cnpm npm install --save vue-clipboard2 2 ...
- 清除浮动以及:after元素
http://www.iyunlu.com/demo/enclosing-float-and-clearing-float/index.html 以上这篇示意图把清除浮动的几种方法讲的非常清楚了,其中 ...
- CentOS7系列--1.2CentOS7基本设置
CentOS7基本设置 1. 查看相关信息 1.1. 查看系统信息 1.1.1. 查看系统位数 方法1: [root@centos7 ~]# uname -a Linux centos7.smartm ...
- 使用 RamMap 清理内存 How to Use RamMap to Empty System Working Set
使用 RamMap 清理内存 In this post I want to introduce RamMap by Microsoft. It’s a free tool you can use to ...
- Vue项目中引用vue-resource步骤
直接上步骤: 1.通过命令,进入到当前项目所在目录 2.输入以下命令npm install vue-resource --save 3.安装完毕后,在main.js中导入,如下: import Vue ...
- Android app启动是出现白屏或者黑屏如何解决?
1.为什么 APP 启动时会出现白屏或者黑屏? 当打开一个 Activity 时,如果这个 Activity 所属的应用还没有在运行,系统会为这个 Activity 所属的应用创建一个进程,但进程的创 ...
- 【Python】Java程序员学习Python(四)— 内置方法和内置变量
<假如爱有天意> 当天边那颗星出现,你可知我又开始想念,有多少爱恋只能遥遥相望,就像月光洒向海面,年少的我们曾以为,相爱的人就能到永远,当我们相信情到深处在一起,听不见风中的叹息,谁知道爱 ...
- Angular-学习。
今天刚学了点关于Angular的知识,就迫不及待的想跟大家来分享. 1.angular.extend ( )方法可以把一个或多个对象中的方法和属性扩展到一个目的对象中. <script typ ...