MyBatis源码解析——获取SqlSessionFactory方式

目录
  • MyBatis源码解析_获取SqlSessionFactory
    • 首先从Resources.getResourceAsReader(path)
    • 进入到SqlSessionFactoryBuilder.build(Reader)方法中
    • 进入到mapperElement(XNode)方法后
    • 如果子节点名字不是package
    • 经过一系列的解析,终于完成了
  • 用MyBatis的配置文件获取SqlSessionFactory

MyBatis源码解析_获取SqlSessionFactory

我们都知道,在Mybatis中,对数据库的增删改查,实际上是由SqlSession来操作的,而SqlSession又是从SqlSessionFactory中得到的,那么问题来了,SqlSessonFactory是如何获得的呢?我们一起来解读一下Mybatis是如何加载配置文件,从而获取SqlSessionFactory的。

首先从Resources.getResourceAsReader(path)

传入我们mybatis全局配置文件得到一个输入流InputStream,这里用Reader来接收。然后new一个SqlSessionFactoryBuilder对象,这是干嘛呢,这个对象里有一个build(Reader)方法,可以将我们传入的Reader,经过一系列的解析过程,返回给我们一个SqlSessionFactory实例,这样我们就得到了想要的SqlSessionFactory了,估计要是这么就结束了,读者会不会打死我呀(哈哈)。

所以我们就详细说一下中间的解析过程。

进入到SqlSessionFactoryBuilder.build(Reader)方法中

它会再次调用build(Reader,environment(默认是null),Properties(默认是null))方法,在这里,根据我们传入的参数先new出一个XMLConfigBuilder对象,称为parser(就是个解析器),然后parser调用它的parse()方法,parse()方法中有一个parseConfiguration(parser.evalNode("/configuration"))方法,我们知道mybatis的全局配置文件是以configuration作为根节点的,而且各个子节点是有严格顺序的,这里就是找到configuration根节点,来分别解析根节点下的每个子节点,然后将解析结果放在一个Configuration中。

解析节点是调用XpathParser.evalNode(root , expression),返回一个XNode,当作参数,放在一个**Element(XNode)方法中去处理节点里每一个信息。这里我们选一个mapperElement(root.evalNode("mappers"))来看看,它是如何解析mappers这个子节点的。

进入到mapperElement(XNode)方法后

先去判断传入的节点是否为null,不为null则解析XNode下的每一个孩子节点,(在mappers标签下,可以插入两种子节点,一种是package,这种做法,要求接口和xml文档在同一个包下,另一种是mapper,mapper节点里有三种属性,分别是resource,url,class,至多只能选一种)。

这里我我们来判断子节点名字是否为"package",如果是,将package节点中的name取出,调用Configuration.addMappers(mapperPackage)方法,实际上调用MapperRegistry.addMappers(packeagename)方法,在这里,又new出了一个ResolverUtil<Class<?>>对象resolverUtil,它可以通过find()方法,找到该包下所有的所有的class或是别的文件,然后筛选出所有.class文件(不是class文件不要),如果是接口的话(不是接口不管),new出一个MapperAnnotationBuilder对象parser(实际上也是个解析器),调用parser.parse()方法,加载与接口名相同的XML文件,保存在configuration中。

如果子节点名字不是package

则取出"resource"、"url"、"class"等属性,分别进行判空,如果属性resource中有值,先将resource所对应的xml文件给转成一个InputStream,再new出一个XMLMapperBuilder(inputStream,configuration,resource)对象mapperParser(这里也是个解析器),调用parse()方法,对接口里所对应的XML文件去解析,具体解析过程和解析mybatis全局配置文件比较类似。

在解析每一个增删改查标签,都会new一个mappedStatement对象statement(这里是通过它的静态内部类Builder来new的),相当于一个MappedStatemet就代表了一个增删改查的详细信息 ,同样MappedStatement也保存在Configuration中。

对于url中有值,过程和resource那个一样,这里不作讲述。对于mapperClass中有值,通过全类名反射,拿到对应的接口,调用configuration.addMapper(mapperInterface)方法,具体过程和package那个一样,也不再讲述。

经过一系列的解析,终于完成了

mappers节点的所有信息也都保存在Configuration中。这个时候回到SqlSessionFactoryBuilder中,将返回的Configuration对象作为参数,调用它的build(configuration)方法,这里是关键的一步,此时根据configuration,new出了一个DefaultSqlSessionFactory对象返回给我们。

我们来看一下DefaultSqlSessionFactory这个类有啥特别的呢,它实现了SqlSessionFactory接口,这个接口里有很多openSession()的重载方法,原来如此,这里我们终于得到了SqlSessionFactory,也就是一个DefaultSqlSessionFactory对象,这个对象里保存着我们的Configuration,而Configuration里又保存着我们全局配置文件里的所有信息,以及**mapper.xml文件里所有信息。

如图所示。

好啦,SqlSessionFactory获取过程就讲到这里啦,想要了解更多细节的童鞋,也可以自己去一步步debug,跟踪源码,了解整个过程

用MyBatis的配置文件获取SqlSessionFactory

import java.io.IOException;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
public class GetSqlSessionFactory {
    private static SqlSessionFactory sqlSessionFactory;
    static{
        String rs="mybatis-config.xml";
        try {
            Reader reader=Resources.getResourceAsReader(rs);
            SqlSessionFactoryBuilder builder=new SqlSessionFactoryBuilder();
            sqlSessionFactory=builder.build(reader);
            //sqlSessionFactory.getConfiguration().addMappers("com.hengtian.mapper");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public  static SqlSessionFactory getInstance(){
        return sqlSessionFactory;
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • 解析Mybatis SqlSessionFactory初始化原理

    目录 引言 SqlSessionFactory 不使用 XML 构建 SqlSessionFactory SqlSessionFactoryBuilder 拓展 引言 现在内卷越来越严重,关于常用的ORM框架Mybatis,小编准备了三篇文章,分别将介绍SqlSessionFactory初始化原理.SqlSession执行流程,Mybatis代理模式运行方式与最终总结,这是第一篇,感兴趣的朋友可以持续关注. SqlSessionFactory 每个基于 MyBatis 的应用都是以一个 SqlS

  • Java异常 Factory method'sqlSessionFactory'rew exception;ested exception is java.lang.NoSuchMethodError:

    springboot 引入mybatis-plus后报错: Factory method 'sqlSessionFactory' threw exception; nested exception is java.lang.NoSuchMethodError: com.baomidou.mybatisplus.entity.GlobalConfiguration.getWorkerId()Ljava/lang/Long; org.apache.ibatis.binding.BindingExce

  • Springboot 配置SqlSessionFactory方式

    目录 Springboot 配置SqlSessionFactory Springboot SqlSessionFactory错误 Springboot 配置SqlSessionFactory Spring官方提供了比较完善的数据库配置,但是某些情况下需要自己手动加载(如:配置多数据源) 以下是我搜集并整理出来的一个configuration,不足之处或错误请大家提出并指正 package cn.xt.config; import org.mybatis.spring.SqlSessionFact

  • mybatis初始化SqlSessionFactory失败的几个原因分析

    目录 mybatis初始化SqlSessionFactory失败 总结原因有几点 SqlSessionFactory异常 mybatis初始化SqlSessionFactory失败 总结原因有几点 1.resources中的xml配置文件放错位置或者是放的太深加载不到 比如 RoleDao因为放的比较包中包中所以扫描不到 2.xml文件里面有错文 比如mapper namespace的相对路径有问题 导致初始化错误 SqlSessionFactory异常 org.springframework.

  • 关于springboot中对sqlSessionFactoryBean的自定义

    目录 springboot sqlSessionFactoryBean自定义 代码如下 以上配置也可以通过properties文件配置 springboot启动报找不到sqlSessionFactory springboot sqlSessionFactoryBean自定义 1.新建一个配置类,加上configuration注解 2.定制化SqlSessionFactoryBean,然后交给容器管理 代码如下 @Configuration public class MybatisConfig {

  • Spring3 整合MyBatis3 配置多数据源动态选择SqlSessionFactory详细教程

    一.摘要 这篇文章将介绍Spring整合Mybatis 如何完成SqlSessionFactory的动态切换的.并且会简单的介绍下MyBatis整合Spring中的官方的相关代码. Spring整合MyBatis切换SqlSessionFactory有两种方法 第一. 继承SqlSessionDaoSupport,重写获取SqlSessionFactory的方法. 第二.继承SqlSessionTemplate 重写getSqlSessionFactory.getConfiguration和Sq

  • 详解 MapperScannerConfigurer之sqlSessionFactory注入方式

    MapperScannerConfigurer之sqlSessionFactory注入方式讲解 首先,Mybatis中的有一段配置非常方便,省去我们去写DaoImpl(Dao层实现类)的时间,这个配置就是包扫描.... 让我们先来看一段代码: <!-- 4:配置扫描Dao接口的包,动态实现Dao接口,注入到Spring容器中 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">

  • MyBatis源码解析——获取SqlSessionFactory方式

    目录 MyBatis源码解析_获取SqlSessionFactory 首先从Resources.getResourceAsReader(path) 进入到SqlSessionFactoryBuilder.build(Reader)方法中 进入到mapperElement(XNode)方法后 如果子节点名字不是package 经过一系列的解析,终于完成了 用MyBatis的配置文件获取SqlSessionFactory MyBatis源码解析_获取SqlSessionFactory 我们都知道,在

  • Mybatis源码解析之事务管理

    目录 Mybatis事务管理 和Spring整合后的事务管理 Mybatis事务管理 我们可以在mybatis-config.xml中配置事务管理器的实现 <transactionManager type="JDBC"/> 当值为JDBC时,事务管理实现类为JdbcTransaction,底层利用数据库的Connection来管理事务 当值为MANAGED时,事务管理实现类为ManagedTransactionFactory,但它对事务的管理是一个空实现,将事务管理交给外部

  • MyBatis源码解析之Transaction事务模块

    目录 1.回顾 2.事务模块 2.1 事务接口 2.2 MyBatis事务类型 2.3 JDBC事务模型 2.4 关于自动提交 2.5 问题 1.回顾 之前介绍了Environment环境类,这其实是一个单例类,在MyBatis运行开启后只会存在一个唯一的环境实例,虽然我们可以在Configuration配置文件中配置多个环境,但是项目运行中只会存在其中的一个,一般项目会存在开发环境和测试环境.生产环境三大环境,其是否可以设置到配置文件中,在开发时使用开发环境,测试时使用测试环境,正式运营时可以

  • 【MyBatis源码全面解析】MyBatis一二级缓存介绍

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相同的查询语句,完全可以把查询结果存储起来,下次查询同样的内容的时候直接从内存中获取数据即可,这样在某些场景下可以大大提升查询效率. MyBatis的缓存分为两种: 一级缓存,一级缓存是SqlSession级别的缓存,对于相同的查询,会从缓存中返回结果而不是查询数据库 二级缓存,二级缓存是Mapper

  • MyBatis3源码解析之如何获取数据源详解

    目录 前言 jdbc 传统JDBC弊端 思考 源码分析 获取数据源 总结 前言 上文讲的MyBatis部署运行且根据官网运行了一个demo:一步到位部署运行MyBatis3源码<保姆级> jdbc 再贴一个JDBC运行的测试方法,流程为: 加载JDBC驱动: 获取数据库连接: 创建JDBC Statements对象: 设置SQL语句的传入参数: 执行SQL语句并获得查询结果; 对查询结果进行转换处理并将处理结果返回; 释放相关资源(关闭Connection,关闭Statement,关闭Resu

  • 解析MyBatis源码实现自定义持久层框架

    目录 自定义框架设计 自定义框架实现 使用端 框架端 自定义框架设计 使用端 : 提供核⼼配置⽂件: sqlMapConfig.xml : 存放数据源信息,引⼊mapper.xml Mapper.xml : sql语句的配置⽂件信息 框架端: 1.读取配置⽂件 读取完成以后以流的形式存在,我们不能将读取到的配置信息以流的形式存放在内存中,不好操作,可以创建JavaBean来存储 (1)Configuration : 存放数据库基本信息.Map<唯⼀标识,Mapper>, 唯⼀标识:namesp

  • MyBatis源码剖析之Mapper代理方式详解

    目录 源码剖析-getmapper() 源码剖析-invoke() 具体代码如下: //前三步都相同 InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml"); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream); SqlSession sqlSess

  • Netty分布式ByteBuf使用的底层实现方式源码解析

    目录 概述 AbstractByteBuf属性和构造方法 首先看这个类的属性和构造方法 我们看几个最简单的方法 我们重点关注第二个校验方法ensureWritable(length) 我们跟到扩容的方法里面去 最后将写指针后移length个字节 概述 熟悉Nio的小伙伴应该对jdk底层byteBuffer不会陌生, 也就是字节缓冲区, 主要用于对网络底层io进行读写, 当channel中有数据时, 将channel中的数据读取到字节缓冲区, 当要往对方写数据的时候, 将字节缓冲区的数据写到cha

  • spring获取bean的源码解析

    介绍 前面一章说了AbstractApplicationContext中的refresh方法中的invokeBeanFactoryPostProcessors.主要是调用BeanFactoryPostProcessor.其中也有获取bean的过程,就是beanFactory.getBean的方法.这一章就说下getBean这个方法.由于spring中获取bean的方法比较复杂,涉及到的流程也非常多,这一章就先说下整个大体的流程.其中的细节会在后面也会慢慢说. 源码 直接看源码吧 @Overrid

  • Netty分布式ByteBuf的分类方式源码解析

    目录 ByteBuf根据不同的分类方式 会有不同的分类结果 1.Pooled和Unpooled 2.基于直接内存的ByteBuf和基于堆内存的ByteBuf 3.safe和unsafe 上一小节简单介绍了AbstractByteBuf这个抽象类, 这一小节对其子类的分类做一个简单的介绍 ByteBuf根据不同的分类方式 会有不同的分类结果 我们首先看第一种分类方式 1.Pooled和Unpooled pooled是从一块内存里去取一段连续内存封装成byteBuf 具体标志是类名以Pooled开头

随机推荐