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

 更新时间:2021年12月16日 10:31:38   作者:rz_0212  
这篇文章主要介绍了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;
    }    
}

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

相关文章

  • 详谈Lock与synchronized 的区别

    详谈Lock与synchronized 的区别

    下面小编就为大家带来一篇详谈Lock与synchronized 的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Spring中ApplicationEventPublisher发布订阅模式的实现

    Spring中ApplicationEventPublisher发布订阅模式的实现

    本文主要介绍了Spring中ApplicationEventPublisher发布订阅模式的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • mybatis高级映射一对多查询实现代码

    mybatis高级映射一对多查询实现代码

    本篇文章主要介绍了mybatis高级映射一对多查询实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-04-04
  • SpringCloudAlibaba微服务调用组件OpenFeign的方法

    SpringCloudAlibaba微服务调用组件OpenFeign的方法

    Feign是Netflix开发的声明式、模板化的HTTP客户端,其灵感来自Retrofit、JAXRS-2.0以及WebSocket,Feign可帮助我们更加便捷、优雅地调用HTTP API,这篇文章主要介绍了SpringCloudAlibaba微服务调用组件OpenFeign,需要的朋友可以参考下
    2024-07-07
  • Spring 整合 MyBatis的实现步骤

    Spring 整合 MyBatis的实现步骤

    SpringMVC 本来就是 Spring 框架的一部分,这两者无须再做整合,所以 SSM 整合的关键就是Spring对MyBatis的整合,三大框架整合完成后,将以 Spring 为核心,调用有关资源,高效运作,这篇文章主要介绍了 Spring 整合 MyBatis的实现步骤,需要的朋友可以参考下
    2023-02-02
  • JDK version和class file version(Class编译版本号)对应关系解读

    JDK version和class file version(Class编译版本号)对应关系解读

    这篇文章主要介绍了JDK version和class file version(Class编译版本号)对应关系,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Java注解Annotation与自定义注解详解

    Java注解Annotation与自定义注解详解

    本文全面讲述了Java注解Annotation与Java自定义注解及相关内容,大家可以认真看看
    2018-03-03
  • java System类和Arrays类详解

    java System类和Arrays类详解

    这篇文章主要介绍了java System类和Arrays类详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • Java 通过API操作GraphQL

    Java 通过API操作GraphQL

    这篇文章主要介绍了Java 通过API操作GraphQL的方法,帮助大家更好的理解和学习使用Java,感兴趣的朋友可以了解下
    2021-05-05
  • SpringBoot关于List集合的校验方式

    SpringBoot关于List集合的校验方式

    这篇文章主要介绍了SpringBoot关于List集合的校验方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07

最新评论