@

相关文章推荐
mybatis 缓存的使用, 看这篇就够了
mybatis源码-解析配置文件(四)之配置文件Mapper解析

1. 简介

本文章主要讲解的是, xxxMapper.xml 文件中, cache 节点的源码。

2. 解析

XMLMapperBuilder.cacheElement() 方法主要负责解析 <cache>

  1. private void cacheElement(XNode context) throws Exception {
  2. if (context != null) {
  3. // 获取 type 节点的属性, 默认是 PERPETUAL
  4. String type = context.getStringAttribute("type", "PERPETUAL");
  5. // 通过 type 值, 查找对应 Cache 接口的实现
  6. Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
  7. // eviction 属性, eviction 对应的是回收策略, 默认为 LRU。
  8. String eviction = context.getStringAttribute("eviction", "LRU");
  9. // 解析 eviction 属性指定的 Cache 装饰器类型
  10. Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
  11. // flushInterval 对应刷新间隔, 单位毫秒, 默认值不设置, 即没有刷新间隔, 缓存仅仅在刷新语句时刷新。
  12. Long flushInterval = context.getLongAttribute("flushInterval");
  13. // size 对应为引用的数量,即最多的缓存对象数据。
  14. Integer size = context.getIntAttribute("size");
  15. // readOnly 为只读属性, 默认为 false, 即可读写
  16. boolean readWrite = !context.getBooleanAttribute("readOnly", false);
  17. // blocking 为阻塞, 默认值为 false。 当指定为 true 时将采用 BlockingCache 进行封装
  18. boolean blocking = context.getBooleanAttribute("blocking", false);
  19. // 获取 <cache> 属性节点下的子节点, 用于初始化二级缓存
  20. Properties props = context.getChildrenAsProperties();
  21. // 通过 MapperBuilderAssistant 创建 Cache 对象, 并将其添加到 COnfiguration 中
  22. builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
  23. }
  24. }

其中, type 的对应类型 PERPETUAL

  1. // PerpetualCache.class 为 org.apache.ibatis.cache.impl.PerpetualCache
  2. typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);

其他的就是获取属性, 有的有对应的默认值。

最后需要将这些属性, 通过 MapperBuilderAssistant.useNewCache() 进行缓存设置。

  1. public Cache useNewCache(Class<? extends Cache> typeClass,
  2. Class<? extends Cache> evictionClass,
  3. Long flushInterval,
  4. Integer size,
  5. boolean readWrite,
  6. boolean blocking,
  7. Properties props) {
  8. // 建造者模式
  9. Cache cache = new CacheBuilder(currentNamespace)
  10. .implementation(valueOrDefault(typeClass, PerpetualCache.class))
  11. .addDecorator(valueOrDefault(evictionClass, LruCache.class))
  12. .clearInterval(flushInterval)
  13. .size(size)
  14. .readWrite(readWrite)
  15. .blocking(blocking)
  16. .properties(props)
  17. .build();
  18. // 将对象添加到 configuration 中
  19. configuration.addCache(cache);
  20. // 给当前命名空间的缓存成员变量赋值
  21. currentCache = cache;
  22. return cache;
  23. }

该函数创建对应的 Cache 对象, 该对象的 idcurrentNamespace(当前mapper.xml 的 namespace)

  1. public Cache build() {
  2. // 设置默认的实现, type 和 lru 对应的类不为空
  3. setDefaultImplementations();
  4. // 通过反射创建对象
  5. Cache cache = newBaseCacheInstance(implementation, id);
  6. // 根据<cache>节点的子节点<property>, 初始化Cache对象
  7. setCacheProperties(cache);
  8. // issue #352, do not apply decorators to custom caches
  9. // 如果是PerpetualCache类型, 使用 decorators 中的装饰器来包装cache, 并设置属性
  10. if (PerpetualCache.class.equals(cache.getClass())) {
  11. for (Class<? extends Cache> decorator : decorators) {
  12. cache = newCacheDecoratorInstance(decorator, cache);
  13. setCacheProperties(cache);
  14. }
  15. // mybatis 自己提供的标准装饰器
  16. cache = setStandardDecorators(cache);
  17. } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
  18. // 如果不是 LoggingCache 子类, 则添加 LoggingCache 装饰器
  19. cache = new LoggingCache(cache);
  20. }
  21. return cache;
  22. }

将对象添加到 configuratin 中。

  1. public void addCache(Cache cache) {
  2. caches.put(cache.getId(), cache);
  3. }

对应的成员变量为

  1. protected final Map<String, Cache> caches = new StrictMap<>("Caches collection");

StrictMap 类型。该对象将 namespace 与 缓存对象 Cache 对应起来了。 而 namespacexxxMapper.xml 的标识。

3 StrictMap

StrictMap 有什么特殊的地方, 为什么不直接用 HashMap 呢?

3.1 区别HashMap:键必须为String

  1. protected static class StrictMap<V> extends HashMap<String, V>

3.2 区别HashMap:多了成员变量 name

多了一个 name 成员变量, 而且该变量是必须设置的

所有的构造函数都需要

  1. public StrictMap(String name, int initialCapacity, float loadFactor) {
  2. super(initialCapacity, loadFactor);
  3. this.name = name;
  4. }
  5. public StrictMap(String name, int initialCapacity) {
  6. super(initialCapacity);
  7. this.name = name;
  8. }
  9. public StrictMap(String name) {
  10. super();
  11. this.name = name;
  12. }
  13. public StrictMap(String name, Map<String, ? extends V> m) {
  14. super(m);
  15. this.name = name;
  16. }

3.3 区别HashMap:key 的处理多了一些变化

3.3.1 put

  1. public V put(String key, V value) {
  2. // 是否存在 key, 存在则直接报异常
  3. if (containsKey(key)) {
  4. throw new IllegalArgumentException(name + " already contains value for " + key);
  5. }
  6. // 获取 shortKey
  7. if (key.contains(".")) {
  8. // 将 key 以 . 分割, 并获取最后一项作为 shortKey
  9. final String shortKey = getShortName(key);
  10. if (super.get(shortKey) == null) {
  11. // 如果 shorKey 对应在 Map 中没有值, 则放入
  12. super.put(shortKey, value);
  13. } else {
  14. // 如果 shorKey 对应在 Map 中有值, 则放入一个 Ambiguity 类
  15. super.put(shortKey, (V) new Ambiguity(shortKey));
  16. }
  17. }
  18. // key 也会放一个 value
  19. return super.put(key, value);
  20. }

3.3.2 shortKey

关于 shortKey, 其实就是我们以全限定名作为属性时, 它取得是分隔符分割后最后的一项。

  1. // 将 key 以 . 分割, 并获取最后一项作为 shortKey
  2. private String getShortName(String key) {
  3. final String[] keyParts = key.split("\\.");
  4. return keyParts[keyParts.length - 1];
  5. }

shortKey 它的作用就是类似一个模糊查询的功能, 比如说我们要调用的是 com.mybatis.homejim.mapper.StudentMapper.selectAll 这个函数, 我们可以写

  1. selectList("com.mybatis.homejim.mapper.StudentMapper.selectAll");

mybatis 中加入 shortKey 之后, 我们只需要写

  1. selectList("selectAll");

但是, 在实际使用时用处不大, 很多函数基本都是会是二义性的, 不明白为何不取消。

3.3.3 Ambiguity

AmbiguityStrictMap 中的静态内部类。

  1. protected static class Ambiguity {
  2. final private String subject;
  3. public Ambiguity(String subject) {
  4. this.subject = subject;
  5. }
  6. public String getSubject() {
  7. return subject;
  8. }
  9. }

其作用记录存在二义性的 key, 告诉使用者, 你的这个 key 是二义性的。

3.3.4 get


  1. public V get(Object key) {
  2. // value 为空则报错
  3. V value = super.get(key);
  4. if (value == null) {
  5. throw new IllegalArgumentException(name + " does not contain value for " + key);
  6. }
  7. // 二义性也报错
  8. if (value instanceof Ambiguity) {
  9. throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name
  10. + " (try using the full name including the namespace, or rename one of the entries)");
  11. }
  12. // 正常情况下应该是返回
  13. return value;
  14. }

一起学 mybatis

你想不想来学习 mybatis? 学习其使用和源码呢?那么, 在博客园关注我吧!!

我自己打算把这个源码系列更新完毕, 同时会更新相应的注释。快去 star 吧!!

mybatis最新源码和注释

mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)的更多相关文章

  1. mybatis源码分析(三)------------映射文件的解析

    本篇文章主要讲解映射文件的解析过程 Mapper映射文件有哪几种配置方式呢?看下面的代码: <!-- 映射文件 --> <mappers> <!-- 通过resource ...

  2. MyBatis源码分析(1)-MapConfig文件的解析

    1.简述 MyBatis是一个优秀的轻ORM框架,由最初的iBatis演化而来,可以方便的完成sql语句的输入输出到java对象之间的相互映射,典型的MyBatis使用的方式如下: String re ...

  3. MyBatis源码分析(四):SQL执行过程分析

    一.获取Mapper接口的代理 根据上一节,Mybatis初始化之后,利用sqlSession(defaultSqlSession)的getMapper方法获取Mapper接口 1 @Override ...

  4. mybatis源码分析(四)---------------代理对象的生成

    在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...

  5. 【mybatis源码学习】mybtias基础组件-占位符解析器

    一.占位符解析器源码 1.占位符解析器实现的目标 通过解析字符串中指定前后缀中的字符,并完成相应的功能. 在mybtias中的应用,主要是为了解析Mapper的xml中的sql语句#{}中的内容,识别 ...

  6. mybatis 源码分析(四)一二级缓存分析

    本篇博客主要讲了 mybatis 一二级缓存的构成,以及一些容易出错地方的示例分析: 一.mybatis 缓存体系 mybatis 的一二级缓存体系大致如下: 首先当一二级缓存同时开启的时候,首先命中 ...

  7. mybatis源码学习(三):MappedStatement的解析过程

    我们之前介绍过MappedStatement表示的是XML中的一个SQL.类当中的很多字段都是SQL中对应的属性.我们先来了解一下这个类的属性: public final class MappedSt ...

  8. mybatis源码学习(四):动态SQL的解析

    之前的一片文章中我们已经了解了MappedStatement中有一个SqlSource字段,而SqlSource又有一个getBoundSql方法来获得BoundSql对象.而BoundSql中的sq ...

  9. mybatis源码-解析配置文件(四)之配置文件Mapper解析

    在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...

随机推荐

  1. (网页)习惯了CS回车操作人员,操作BS网页表单也是回车666

    1.第一步把表单,里面需要回车的input,或者是其他的表单按钮给一个clsss,例如下面的$('.cls'); 2.第二步,  把下面的代码复制过去,填写完最后一个自动提交:$("#sav ...

  2. php get接口,并在浏览器中以json格式返回查找到的数据

    php查询数据有6个步骤,分别为: 连接数据库服务器,使用的命令为:mysql_connect("服务器名称","用户名","密码") 选择 ...

  3. Spark Shuffle机制

    Spark Shuffle 一.HashShuffle 普通机制:产生磁盘小文件的数量为:M(map task number)*R(reduce task number) 过程: 1.map task ...

  4. JAVA多线程的问题以及处理(一)【转】

    多线程编程为程序开发带来了很多的方便,但是也带来了一些问题,这些问题是在程序开发过程中必须进行处理的问题. 这些问题的核心是,如果多个线程同时访问一个资源,例如变量.文件等,时如何保证访问安全的问题. ...

  5. ZooKeeper使用命令大全

    stat path [watch]    set path data [version]    ls path [watch]    delquota [-n|-b] path    ls2 path ...

  6. Error in Log_event::read_log_event(): 'Event too small', data_len: 0, event_type: 0

    MySQL主从复制报错如下: 2018-04-11 09:11:16 2400 [Note] Slave SQL thread initialized, starting replication in ...

  7. C#从http上拿返回JSON数据

    C#如何拿到从http上返回JSON数据? 第一章:C#如何拿到从http上返回JSON数据? 第二章:C#如何解析JSON数据?(反序列化对象) 第三章:C#如何生成JSON字符串?(序列化对象) ...

  8. [福大软工] Z班 团队第一次作业—团队展示成绩公布

    [福大软工] Z班 团队第一次作业-团队展示成绩公布 作业地址 http://www.cnblogs.com/easteast/p/7511264.html 作业要求 队员姓名与学号(标记组长),其中 ...

  9. 关于Three.js基本几何形状

    一.有关球体SphereGeometry构造函数参数说明 SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLeng ...

  10. 【C编程基础】C程序常用函数

    基础知识 1.const const 修饰的数据类型是指常类型,常类型的变量或对象的值是不能被更新的. ; 或 ; //在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再改变它了 ...