通过实例结合源码的方式解读,其中涉及到的文件来自于笔者的Github毕设项目,引用的jar包为mybatis-spring-1.3.0.jar

Mybatis

Mybatis是基于ORM(Object relation mapping)思想而开发的框架插件,本质原理用一句笔者的话便是使用了JAVA连接数据库的方式来执行相应的SQL(PreparedStatement),并在此基础上提供了丰富的动态SQL配置以及缓存等概念。(后续文章会提及)

其基本上是企业与传统数据库(Oracle/Mysql等)交互常用的数据库持久层框架,以JAVA语言来说,其与Spring的搭配使用也是广为流传。

本文将从源码的角度浅析Mybatis与Spring的亲密搭配

范例

笔者本文只关注SqlSessionFactoryBean的配置,样例如下

    <!--数据源,引用common-pool包的数据源类-->
<bean id="dataSource-mysql" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
<property name="initialSize" value="1" />
<property name="maxActive" value="20" />
</bean> <!--sqlSessionFactoryBean创建-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource-mysql" />
<property name="typeAliasesPackage" value="com.du.wx.model" />
<property name="mapperLocations" value="classpath:com/du/wx/resources/mapper/*.xml"/>
</bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- joggle代表接口 -->
<property name="basePackage" value="com.du.wx.mapper.joggle" />
</bean>

由上述的配置可知,在配置SqlSessionFactory数据库会话工厂Bean对象时必须依赖相应的数据源属性dataSource

SqlSessionFactoryBean

笔者分层次来解析此类

基础内部属性

优先观察SqlSessionFactoryBean的内部属性,代码片段如下

    private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);

    private Resource configLocation;

    private Configuration configuration;

    private Resource[] mapperLocations;

    private DataSource dataSource;

    private TransactionFactory transactionFactory;

    private Properties configurationProperties;

    private SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();

    private SqlSessionFactory sqlSessionFactory;

    //EnvironmentAware requires spring 3.1
private String environment = SqlSessionFactoryBean.class.getSimpleName(); private boolean failFast; private Interceptor[] plugins; private TypeHandler<?>[] typeHandlers; private String typeHandlersPackage; private Class<?>[] typeAliases; private String typeAliasesPackage; private Class<?> typeAliasesSuperType; //issue #19. No default provider.
private DatabaseIdProvider databaseIdProvider; private Class<? extends VFS> vfs; private Cache cache; private ObjectFactory objectFactory; private ObjectWrapperFactory objectWrapperFactory;

常用的属性如下:

configLocation mybatis主配置文件路径,支持classpath语法

mapperLocations 指定mybatis的mapper配置文件,支持classpath语法

dataSource 数据源

typeAliasesPackage 指定model层类名的别名扫描包,这与mapper配置中的parameterTyperesultType搭配使用

InitializingBean复写方法

紧接着看下其复写的afterPropertiesSet()方法,代码如下

  @Override
public void afterPropertiesSet() throws Exception {
//datasource not allowed to be null.
notNull(dataSource, "Property 'dataSource' is required");
notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
"Property 'configuration' and 'configLocation' can not specified with together"); this.sqlSessionFactory = buildSqlSessionFactory();
}

与前文提及的对应,必须确保dataSource属性已经得到配置。

实例化步骤

最后查看关键实例方法buildSqlSessionFactory()方法,由于片段过长,笔者截取几段来进行讲解


Mybatis主文件加载

	Configuration configuration;

    XMLConfigBuilder xmlConfigBuilder = null;
if (this.configuration != null) {
configuration = this.configuration;
if (configuration.getVariables() == null) {
configuration.setVariables(this.configurationProperties);
} else if (this.configurationProperties != null) {
configuration.getVariables().putAll(this.configurationProperties);
}
} else if (this.configLocation != null) {
//如果spring配置中configLocation属性不为空,则加载指定的Mybatis配置
xmlConfigBuilder = new XMLConfigBuilder(this.configLocation.getInputStream(), null, this.configurationProperties);
configuration = xmlConfigBuilder.getConfiguration();
} else {
//否则则采用默认的Mybatis配置,@see Configuration
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Property `configuration` or 'configLocation' not specified, using default MyBatis Configuration");
}
configuration = new Configuration();
configuration.setVariables(this.configurationProperties);
}

通过上述配置表明,内部属性configLocation是非必须配置项


model别名映射扫描

	if (hasLength(this.typeAliasesPackage)) {
//截取typeAliasesPackage属性的包,支持,或;
String[] typeAliasPackageArray = tokenizeToStringArray(this.typeAliasesPackage,ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
for (String packageToScan : typeAliasPackageArray) {
//对应方法的目的是通过扫描包得到其包以及子包目录下的所有Class,然后为每个class注册别名
configuration.getTypeAliasRegistry().registerAliases(packageToScan,
typeAliasesSuperType == null ? Object.class : typeAliasesSuperType);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Scanned package: '" + packageToScan + "' for aliases");
}
}
}

即对内部属性typeAliasesPackage支持,;作为分隔符以加载多个目录,主要是为了方便编程人员使用parameterType/resultType等属性


mapper配置文件加载

	if (!isEmpty(this.mapperLocations)) {
//mapperLocations
for (Resource mapperLocation : this.mapperLocations) {
if (mapperLocation == null) {
continue;
} try {
//对扫描的每个配置文件进行解析,并保存其中的必要参数,后续会分析
XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(),
configuration, mapperLocation.toString(), configuration.getSqlFragments());
xmlMapperBuilder.parse();
} catch (Exception e) {
throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e);
} finally {
ErrorContext.instance().reset();
} if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Parsed mapper file: '" + mapperLocation + "'");
}
}
} else {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");
}
}

关键处理XML配置的mapper文件,用到了mybatis包中的org.apache.ibatis.builder.xml.XMLMapperBuilder类进行解析。这个后续分析


Configuration-所有关于Mybatis的信息均存储在Mybatis包中的org.apache.ibatis.session.Configuration类上

return this.sqlSessionFactoryBuilder.build(configuration);

Spring呢,就通过SqlSessionFactoryBuilder类来创建相应的SqlSessionFactory对象。具体的由于篇幅过长,就放在后文分析。

总结

从上文便可以看出来Spring框架是如何整合Mybatis的,就是这个Mybatis的关键类Configuration。而相应的开关数据库等一系列的功能都是通过Spring的SqlSessionFactory对象来操控的。这也是两者结合最核心的地方

Spring mybatis源码篇章-SqlSessionFactoryBean的更多相关文章

  1. Spring mybatis源码篇章-sql mapper配置文件绑定mapper class类

    前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(二) 背景知识 MappedStatement是mybatis操作sql ...

  2. Spring mybatis源码篇章-MybatisDAO文件解析(二)

    前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(一) 默认加载mybatis主文件方式 XMLConfigBuilder ...

  3. Spring mybatis源码篇章-MybatisDAO文件解析(一)

    前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-SqlSessionFactory 加载指定的mybatis主文件 Mybatis模板文件,其中的属性 ...

  4. Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource

    前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-MybatisDAO文件解析(二) 首先了解下sql mapper的动态sql语法 具体的动态sql的 ...

  5. Spring mybatis源码篇章-MapperScannerConfigurer关联dao接口

    前言:Spring针对Mybatis的XML方式的加载MappedStatement,通过引入MapperScannerConfigurer扫描类来关联相应的dao接口以供Service层调用.承接前 ...

  6. Spring mybatis源码篇章-动态SQL基础语法以及原理

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-Mybatis的XML文件加载 前话 前文通过Spring中配置mapperLocations属性来进行对m ...

  7. Spring mybatis源码篇章-Mybatis的XML文件加载

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-Mybatis主文件加载 前话 前文主要讲解了Mybatis的主文件加载方式,本文则分析不使用主文件加载方式 ...

  8. Spring mybatis源码篇章-Mybatis主文件加载

    通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-SqlSessionFactory 前话 本文承接前文的内容继续往下扩展,通过Spring与Mybatis的 ...

  9. Spring mybatis源码篇章-NodeHandler实现类具体解析保存Dynamic sql节点信息

    前言:通过阅读源码对实现机制进行了解有利于陶冶情操,承接前文Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource SqlNode接口类 publi ...

随机推荐

  1. html5中cookie介绍,封装以及添加,获取,删除

    cookie是储存在用户本地终端上的数据. 在我们登陆网站时有记录密码,也有时间限制比如说7天,5天等等这都是我们利用cookie来写的, 这就是利用了cookie的会话周期,但cookie同时又是不 ...

  2. Vulkan Tutorial 15 Framebuffers

    操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 我们在前面的章节中已经讨论了很多次framebuffers帧缓冲区,到目前为止我们配 ...

  3. HTTPS系列干货(一):HTTPS 原理详解

    HTTPS(全称:HyperText Transfer Protocol over Secure Socket Layer),其实 HTTPS 并不是一个新鲜协议,Google 很早就开始启用了,初衷 ...

  4. canvas水波纹效果

    先看效果 演示效果 自然界中水波纹效果十分麻烦,我这里只是根据水波纹的几个特性,在理想环境下模拟水波纹的扩散效果. 这里应用到的属性有:扩散.波动.折射. 扩散:很好理解,水波纹会从触发原点开始向周围 ...

  5. Centos常用命令及解释

    ps -ef|grep java ps:将某个进程显示出来-A 显示所有程序. -e 此参数的效果和指定"A"参数相同.-f 显示UID,PPIP,C与STIME栏位. grep命 ...

  6. Javascript 严格模式use strict

    一.概述 除了正常运行模式,ECMAscript 5添加了第二种运行模式:“严格模式”(strict mode).顾名思义,这种模式使得Javascript在更严格的条件下运行. 设立”严格模式”的目 ...

  7. ionic 项目中创建侧边栏的具体流程分4步简单学会

    这是在学习ionic时,当时遇到的一些问题,觉得很难,就记笔记下来了,现在觉得如果可以拿来分享,有可能会帮助到遇到同样问题的人 ionic slidemenu 项目流程: cd pretices(自己 ...

  8. solr5.5索引mysql数据(新手总结)

    一 solr5.5环境部署到Eclipse(luna版) solr部署参见:http://blog.csdn.net/csmnjk/article/details/64121765 二 Ik分词器设置 ...

  9. 从String类型字符串的比较到StringBuffer和StringBuilder

    1. String类型 String类源码 为了从本质上理解String类型的特性所在,我们从String类型的源码看起,在源码中String类的注释中存在以下: /**Strings are con ...

  10. linux中怎么进入root用户

    如果你是第一次使用root用户,需要设置root用户密码:passwd root 根据提示输入然后切换到root用户:su root回车输入密码 回车