Mybatis【2.1】-- 从读取流到创建SqlSession发生了什么?

我们使用sqlSession
之前,需要去获取配置文件,获取InputStream
输入流,通过SqlSessionFactoryBuilder
获取sqlSessionFactory
对象,从而获取sqlSession
。
1.Resources.getResourceAsStream("mybatis.xml")到底做了什么?
1.首先我们来看InputStream is = Resources.getResourceAsStream("mybatis.xml");
这句话到底替我们干了什么,下面可以看出在里面调用了另一个内部方法,resource是全局配置的文件名:
2.跟进方法中,我们可以知道在里面调用ClassLoaderWrapper
类的一个实例对象的getResourceAsStream()
方法,这个classLoaderWrapper
怎么来的呢?这个是Resources.class
的一个成员属性,那么这个ClassLoaderWrapper
是什么东西呢?
在Resources.class
中我们只是使用private static ClassLoaderWrapper classLoaderWrapper = new ClassLoaderWrapper();
创建一个classLoaderWrapper
对象。
ClassLoaderWrapper
其实是一个ClassLoader
(类加载器)的包装类,其中包含了几个ClassLoader
对象,一个defaultClassLoader
,一个systemClassLoader
,通过内部控制,可以确保返回正确的类加载器给系统使用。我们可以当成一个mybatis
自定义过的类加载器。
3.我们可以看出调用了下面这个内部方法,里面调用了封装的方法,一个是获取当前的类加载器,另一个是传进来的文件名:
4.查看getClassLoaders()
这个方法,可以看到里面初始化了一个类加载器的数组,里面有很多个类加载器,包括默认的类加载器,当前线程的上下文类加载器,系统类加载器等。
5.进入getResourceAsStream(String resource, ClassLoader[] classLoader)
这个方法内部,我们可以看到里面遍历所有的类加载器,使用类加载器来加载获取InputStream
对象,我们可以知道里面是选择第一个适合的类加载器,如果我们不传类加载器进去,那么第一个自己定义的类加载器就是null,那么就会默认选择第二个默认类加载器,而且我们可以知道如果文件名前面没有加“/
”,获取到空对象的话,会自动加上“/
”再访问一遍:
6.我们进入类加载器加载资源文件的代码中,我们可以看到首先获取全路径的url
,然后再调用openStream()
:
6.1.我们跟进getResource(name)
这个方法,我们可以看到里面都是调用parent
的getResource()
方法,如果已经是父加载器,那么就使用getBootstrapResource(name)
获取,如果获取出来是空的,再根据getBootstrapResource(name)
方法获取。
6.1.1我们跟进去getBootstrapResource(name);
6.1.1.1我们看到getBootstrapClassPath()
这个方法,这个方法的里面调用了引入的包,读取的是类加载器的加载路径,这个方法到此为止,再深入就回不去了:)。
6.1.1.2 我们看ucp.getResource(name)
这个方法,我们可以看到在里面调用了这个方法,这个方法主要是查找缓存,然后遍历找到第一个符合条件的加载器来获取resource
,到此我们不再深究下去,得往上一层回头看:
我们知道getBootstrapResource(name)
里面主要是url(文件资源的路径),然后使用url.openStream()
去获取stream流:
我们来看openConnection()方法,里面调用的是一个抽象方法,获取的是一个URLConnection(url连接对象):
再看getInputStream()这个方法,我们可以看到这是一个接口方法,我们找到FileURLConnection的这个方法,这是一个单线程处理文件URL的inputstream的方法:
到这里,整个获取inputstream的过程已经结束,只要把返回值往上一层返回就可以得到这个配置文件所需要的inputstream。
2. new SqlSessionFactoryBuilder().build(is)的运行原理
首先SqlSessionFactoryBuilder的无参数构造方法是没有任何操作的:
那么我们看build(is)
这个方法,里面调用了一个封装方法,一个是inputstream,一个是string,一个是属性对象:
跟进去,我们可以看到在里面使用了xmlconfigbuilder,也就是xml配置构造器,实例化一个xml配置对象,可想而知,也就是我们的mybatis.xml所对应的配置对象构造器,在里面调用了另一个build()方法:
我们可以看到调用的另一个build方法,也就是使用配置对象构建一个DefaultSqlSessionFactory对象,在上面返回这个对象,也就是我们的sqlsessionFactory。
3. sqlSessionFactory.openSession()获取sqlSession
我们可以看到其实这个是sqlSessionFactory
的一个接口,其实现类是DefaultSqlSessionFactory
,那么方法如下:
我们查看openSessionFromDataSource()
这个方法,从名字可以大概知道是从数据源加载Sqlsession,里面可以指定执行器类型,事物隔离级别,还有是否自动提交,如果不设定,那么默认是null以及false,在方法内主要做的是将配置文件对象的环境取出来构造事务工厂,配置执行器等,返回一个DefaultSqlSession
的实例。
到此为止,一个sqlsession
对象就根据配置文件创建出来了。
此文章仅代表自己(本菜鸟)学习积累记录,或者学习笔记,如有侵权,请联系作者删除。人无完人,文章也一样,文笔稚嫩,在下不才,勿喷,如果有错误之处,还望指出,感激不尽~
技术之路不在一时,山高水长,纵使缓慢,驰而不息。
公众号:秦怀杂货店
__EOF__

本文链接:https://www.cnblogs.com/Damaer/p/13992173.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· Plotly.NET 一个为 .NET 打造的强大开源交互式图表库