给自己的每日一句

不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干。凡他所做的尽都顺利

本文内容整理自《孙哥说Mybatis系列课程》

Cache是在什么时候、什么地点被创建的?

不管是我们使用Mybatis写测试程序,还是在真实企业级项目中使用Mybatis,Mybatis框架被启动加载的前几行代码一定是如下:

        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);SqlSession sqlSession = sqlSessionFactory.openSession();

然后我们的二级缓存Cache对象就是在这个期间,也就是Mybatis被启动和初始化的时候完成的,那么我们就详细展开吧。

首先:我要告诉大家的是,这个过程一定是在SqlSessionFactory工厂被创建的时候完成的,那就是上述的第二行代码,并且这里应用的是构建者设计模式,这个精华必须隐藏在build()方法中,我们查看一下:

  public SqlSessionFactory build(InputStream inputStream) {return build(inputStream, null, null);}//重载的build方法,真正的精华是在这里public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {try {//将Mybatis和核心配置文件读取成inputStream之后,我们有将他转换成Mybatis中重要的//XMLConfigBuilder对象XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);return build(parser.parse());} catch (Exception e) {throw ExceptionFactory.wrapException("Error building SqlSession.", e);} finally {ErrorContext.instance().reset();try {inputStream.close();} catch (IOException e) {// Intentionally ignore. Prefer previous error.}}}

return build(parser.parse());这里边硬货就多了,build方法就是为了创建

  public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);}

所以,里边的parser.parse()的返回值一定是生成的Configuration对象,原材料就是Mybatis核心配置文件读取到的InputStream,有因为InputStream当中记录了Mapper.xml的路径,所以这些Mapper文件必定也是在这里边解析的。

  public Configuration parse() {if (parsed) {throw new BuilderException("Each XMLConfigBuilder can only be used once.");}parsed = true;parseConfiguration(parser.evalNode("/configuration"));return configuration;}

parser.evalNode(“/configuration”)兄弟们,这玩意用脚趾头都知道,这读的是mybatis-config.xml里边的Configuration标签,这样就把mybatis-config.xml整个文件作为一个Node对象被放到了parseConfiguration方法当中,这个方法的目的从方法上就能看出来,为了构建Configuration对象

  private void parseConfiguration(XNode root) {try {//issue #117 read properties firstpropertiesElement(root.evalNode("properties"));Properties settings = settingsAsProperties(root.evalNode("settings"));loadCustomVfs(settings);typeAliasesElement(root.evalNode("typeAliases"));pluginElement(root.evalNode("plugins"));objectFactoryElement(root.evalNode("objectFactory"));objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));reflectorFactoryElement(root.evalNode("reflectorFactory"));settingsElement(settings);// read it after objectFactory and objectWrapperFactory issue #631environmentsElement(root.evalNode("environments"));databaseIdProviderElement(root.evalNode("databaseIdProvider"));typeHandlerElement(root.evalNode("typeHandlers"));mapperElement(root.evalNode("mappers"));} catch (Exception e) {throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);}}

兄弟们,眼熟了吧,这不就是mybatis-config.xml里边的一个一个的标签么,一个一个的排队解析,看最后一行,这玩意里边存储的不就是Mapper标签么,所以Mapper.xml必定就是在这里边解析的,再加上我们知道Cache标签是写在Mapper.xml里边的,所以Cache对象必是在里边创建的。

  private void mapperElement(XNode parent) throws Exception {if (parent != null) {for (XNode child : parent.getChildren()) {if ("package".equals(child.getName())) {String mapperPackage = child.getStringAttribute("name");configuration.addMappers(mapperPackage);} else {String resource = child.getStringAttribute("resource");String url = child.getStringAttribute("url");String mapperClass = child.getStringAttribute("class");if (resource != null && url == null && mapperClass == null) {ErrorContext.instance().resource(resource);InputStream inputStream = Resources.getResourceAsStream(resource);XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());mapperParser.parse();} else if (resource == null && url != null && mapperClass == null) {ErrorContext.instance().resource(url);InputStream inputStream = Resources.getUrlAsStream(url);XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());mapperParser.parse();} else if (resource == null && url == null && mapperClass != null) {Class<?> mapperInterface = Resources.classForName(mapperClass);configuration.addMapper(mapperInterface);} else {throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");}}}}}

兄弟们,XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());这玩意不就是在读Mapper.xml文件么,mapperParser.parse();又去parse去了,我们进去看看

  public void parse() {if (!configuration.isResourceLoaded(resource)) {configurationElement(parser.evalNode("/mapper"));configuration.addLoadedResource(resource);bindMapperForNamespace();}parsePendingResultMaps();parsePendingCacheRefs();parsePendingStatements();}

configurationElement兄弟们,看到名字还不明白么,这是在解析Mapper.xml当中的元素解析到Configurantion对象当中呀,Cache标签也是其中的一个元素呀

  private void configurationElement(XNode context) {try {String namespace = context.getStringAttribute("namespace");if (namespace == null || namespace.equals("")) {throw new BuilderException("Mapper's namespace cannot be empty");}builderAssistant.setCurrentNamespace(namespace);cacheRefElement(context.evalNode("cache-ref"));cacheElement(context.evalNode("cache"));parameterMapElement(context.evalNodes("/mapper/parameterMap"));resultMapElements(context.evalNodes("/mapper/resultMap"));sqlElement(context.evalNodes("/mapper/sql"));buildStatementFromContext(context.evalNodes("select|insert|update|delete"));} catch (Exception e) {throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);}}
  private void cacheElement(XNode context) throws Exception {if (context != null) {String type = context.getStringAttribute("type", "PERPETUAL");Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);String eviction = context.getStringAttribute("eviction", "LRU");Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);Long flushInterval = context.getLongAttribute("flushInterval");Integer size = context.getIntAttribute("size");boolean readWrite = !context.getBooleanAttribute("readOnly", false);boolean blocking = context.getBooleanAttribute("blocking", false);Properties props = context.getChildrenAsProperties();builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);}}

兄弟们,到这里基本上知道在哪里创建的吧?至于怎么创建,咱们后期出文章玩~

Mybatis源码细节探究:二级缓存Cache对象是在什么时候创建的?相关推荐

  1. 手把手带你阅读Mybatis源码(三)缓存篇

    点击上方"Java知音",选择"置顶公众号" 技术文章第一时间送达! 前言 大家好,这一篇文章是MyBatis系列的最后一篇文章,前面两篇文章:手把手带你阅读M ...

  2. 【转】ABP源码分析十三:缓存Cache实现

    ABP中有两种cache的实现方式:MemoryCache 和 RedisCache. 如下图,两者都继承自ICache接口(准确说是CacheBase抽象类).ABP核心模块封装了MemoryCac ...

  3. mybatis源码很难吗,带你层层拨开Mybatis------缓存的“神秘”面纱

    目录 概述 介绍 一级缓存 一级缓存介绍 一级缓存配置 一级缓存工作流程&源码分析 总结 二级缓存 二级缓存介绍 启⽤⼆级缓存 二级缓存实验 二级缓存源码分析 源码分析 总结 较详细源码分析 ...

  4. Mybatis源码解析(一):环境搭建

    Mybatis源码系列文章 手写源码(了解源码整体流程及重要组件) Mybatis源码解析(一):环境搭建 Mybatis源码解析(二):全局配置文件的解析 Mybatis源码解析(三):映射配置文件 ...

  5. Mybatis源码学习笔记之Mybatis二级缓存

    简介   Mybatis一级缓存是会话级的缓存,而二级缓存则是应用级别的缓存,默认关闭,二级缓存使用不慎可能会导致脏读. 开启方式(SpringBoot+Mybatis)   application. ...

  6. 干翻Mybatis源码系列之第八篇:Mybatis二级缓存的创建和存储

    给自己的每日一句 不从恶人的计谋,不站罪人的道路,不坐亵慢人的座位,惟喜爱耶和华的律法,昼夜思想,这人便为有福!他要像一棵树栽在溪水旁,按时候结果子,叶子也不枯干.凡他所做的尽都顺利 本文内容整理自& ...

  7. MyBatis 源码分析 - 缓存原理

    1.简介 在 Web 应用中,缓存是必不可少的组件.通常我们都会用 Redis 或 memcached 等缓存中间件,拦截大量奔向数据库的请求,减轻数据库压力.作为一个重要的组件,MyBatis 自然 ...

  8. Mybatis 源码探究 (4) 将sql 语句中的#{id} 替换成 ‘?

    Mybatis 源码探究 (4) 将sql 语句中的#{id} 替换成 '? 出于好奇,然后就有了这篇文章啦. 源码给我的感觉,是一座大山的感觉.曲曲折折的路很多,点进去就有可能出不来. 不过慢慢看下 ...

  9. 【MyBatis源码解析】MyBatis一二级缓存

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...

  10. Mybatis 源码探究 (3)创建 SqlSessionFactory对象 执行sqlSession.getMapper()方法

    Mybatis 源码探究 (3)创建 SqlSessionFactory对象 时隔许久,终于又能接着来搞他啦.Mybatis 一起来探究吧. 先笑会再进入主题吧 开始啦 一.new SqlSessio ...

最新文章

  1. opengl 大作业_大学新生作业10米长!网友:确认过眼神,是我画不出的十米长卷……...
  2. go消息服务器吗,Go语言聊天服务器
  3. 1 数列分块入门_线性代数入门——利用分块矩阵简化矩阵乘法运算
  4. xul 创建一个按钮
  5. 如何打造顶级目标检测算法?百度官方揭秘 ECCV2020 双料冠军的理论与实践
  6. pyqt5 窗口设置圆角_pyqt5-30. QWidget设置圆角,使用qss设置失败
  7. 2017年一线城市程序员工资大调查
  8. stm32f4产生100k正弦波_STM32_DAC 实验(正弦波_方波_锯齿波_发生器)
  9. pm2部署next项目
  10. Excel表格导入CAD后,表格内数字后的小数点怎么消除呢?
  11. 计算机多媒体教学的缺点,多媒体教学与传统教学的优劣势探讨-20210716004535.docx-原创力文档...
  12. 软件测试的日常工作是什么
  13. linux字符模式分辨率grub2,Grub2中文指南2---设置、自定义
  14. 4g+uim卡是什么卡_为什么电信4G信号满格网速却很慢?
  15. Android Drawable Resource学习(五)、StateListDrawable
  16. jQuery 过滤方法
  17. 微软不再为 DNS over HTTPS (DoH) 提供 Google PublicDNS 和 Cloudflare DNS 服务提供商
  18. linux 写java_linux下java程序开发
  19. 环境类软件测试项目,软件测试技术、方法和环境
  20. Nginx在Linux(centos7)环境下的下载与安装

热门文章

  1. 函授和成人高考的哪个含金量更高?
  2. DSM: Domain-invariant Stereo Matching Networks 域不变的立体匹配网络
  3. 求全年最高温度(通过mapreduce)
  4. Python笔记【十二】
  5. 计算机辅助数学教学论文,计算机辅助数学教学论文大纲样本大全 计算机辅助数学教学论文大纲如何写...
  6. web服务器--iis
  7. 04.Java 编程入门学习笔记20210307
  8. QT Creator+ ARM Linux开发MQTT程序
  9. 微信小程序开发疑难杂症
  10. CIO的IT战略:盖川崎创新艺术十步曲