mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)

大道之行,天下为公。这篇文章主要讲述mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)相关的知识,希望能为你提供帮助。
@
目录

  • 1. 简介
  • 2. 解析
  • 3 StrictMap
    • 3.1 区别HashMap:键必须为String
    • 3.2 区别HashMap:多了成员变量 name
    • 3.3 区别HashMap:key 的处理多了一些变化
      • 3.3.1 put
      • 3.3.2 shortKey
      • 3.3.3 Ambiguity
      • 3.3.4 get
  • 一起学 mybatis

相关文章推荐
mybatis 缓存的使用, 看这篇就够了
mybatis源码-解析配置文件(四)之配置文件Mapper解析
1. 简介本文章主要讲解的是, xxxMapper.xml 文件中, cache 节点的源码。
2. 解析XMLMapperBuilder.cacheElement() 方法主要负责解析 < cache>
private void cacheElement(XNode context) throws Exception { if (context != null) { // 获取 type 节点的属性, 默认是 PERPETUAL String type = context.getStringAttribute("type", "PERPETUAL"); // 通过 type 值, 查找对应 Cache 接口的实现 Class< ? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type); // eviction 属性, eviction 对应的是回收策略, 默认为 LRU。 String eviction = context.getStringAttribute("eviction", "LRU"); // 解析 eviction 属性指定的 Cache 装饰器类型 Class< ? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction); // flushInterval 对应刷新间隔, 单位毫秒, 默认值不设置, 即没有刷新间隔, 缓存仅仅在刷新语句时刷新。 Long flushInterval = context.getLongAttribute("flushInterval"); // size 对应为引用的数量,即最多的缓存对象数据。 Integer size = context.getIntAttribute("size"); // readOnly 为只读属性, 默认为 false, 即可读写 boolean readWrite = !context.getBooleanAttribute("readOnly", false); // blocking 为阻塞, 默认值为 false。 当指定为 true 时将采用 BlockingCache 进行封装 boolean blocking = context.getBooleanAttribute("blocking", false); // 获取 < cache> 属性节点下的子节点, 用于初始化二级缓存 Properties props = context.getChildrenAsProperties(); // 通过 MapperBuilderAssistant 创建 Cache 对象, 并将其添加到 COnfiguration 中 builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props); } }

其中, type 的对应类型 PERPETUAL
// PerpetualCache.class 为 org.apache.ibatis.cache.impl.PerpetualCache typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);

其他的就是获取属性, 有的有对应的默认值。
最后需要将这些属性, 通过 MapperBuilderAssistant.useNewCache() 进行缓存设置。
public Cache useNewCache(Class< ? extends Cache> typeClass, Class< ? extends Cache> evictionClass, Long flushInterval, Integer size, boolean readWrite, boolean blocking, Properties props) { // 建造者模式 Cache cache = new CacheBuilder(currentNamespace) .implementation(valueOrDefault(typeClass, PerpetualCache.class)) .addDecorator(valueOrDefault(evictionClass, LruCache.class)) .clearInterval(flushInterval) .size(size) .readWrite(readWrite) .blocking(blocking) .properties(props) .build(); // 将对象添加到 configuration 中 configuration.addCache(cache); // 给当前命名空间的缓存成员变量赋值 currentCache = cache; return cache; }

该函数创建对应的 Cache 对象, 该对象的 id 为 currentNamespace(当前mapper.xml 的 namespace)。
public Cache build() { // 设置默认的实现, type 和 lru 对应的类不为空 setDefaultImplementations(); // 通过反射创建对象 Cache cache = newBaseCacheInstance(implementation, id); // 根据< cache> 节点的子节点< property> , 初始化Cache对象 setCacheProperties(cache); // issue #352, do not apply decorators to custom caches // 如果是PerpetualCache类型, 使用 decorators 中的装饰器来包装cache, 并设置属性 if (PerpetualCache.class.equals(cache.getClass())) { for (Class< ? extends Cache> decorator : decorators) { cache = newCacheDecoratorInstance(decorator, cache); setCacheProperties(cache); } // mybatis 自己提供的标准装饰器 cache = setStandardDecorators(cache); } else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) { // 如果不是 LoggingCache 子类, 则添加 LoggingCache 装饰器 cache = new LoggingCache(cache); } return cache; }

将对象添加到 configuratin 中。
public void addCache(Cache cache) { caches.put(cache.getId(), cache); }

对应的成员变量为
protected final Map< String, Cache> caches = new StrictMap< > ("Caches collection");

StrictMap 类型。该对象将 namespace 与 缓存对象 Cache 对应起来了。 而 namespace 是 xxxMapper.xml 的标识。
3 StrictMapStrictMap 有什么特殊的地方, 为什么不直接用 HashMap 呢?
3.1 区别HashMap:键必须为String
protected static class StrictMap< V> extends HashMap< String, V>

3.2 区别HashMap:多了成员变量 name多了一个 name 成员变量, 而且该变量是必须设置的
所有的构造函数都需要
public StrictMap(String name, int initialCapacity, float loadFactor) { super(initialCapacity, loadFactor); this.name = name; }public StrictMap(String name, int initialCapacity) { super(initialCapacity); this.name = name; }public StrictMap(String name) { super(); this.name = name; }public StrictMap(String name, Map< String, ? extends V> m) { super(m); this.name = name; }

3.3 区别HashMap:key 的处理多了一些变化 3.3.1 put
public V put(String key, V value) { // 是否存在 key, 存在则直接报异常 if (containsKey(key)) { throw new IllegalArgumentException(name + " already contains value for " + key); } // 获取 shortKey if (key.contains(".")) { // 将 key 以 . 分割, 并获取最后一项作为 shortKey final String shortKey = getShortName(key); if (super.get(shortKey) == null) { // 如果 shorKey 对应在 Map 中没有值, 则放入 super.put(shortKey, value); } else { // 如果 shorKey 对应在 Map 中有值, 则放入一个 Ambiguity 类 super.put(shortKey, (V) new Ambiguity(shortKey)); } } // key 也会放一个 value return super.put(key, value); }

3.3.2 shortKey
关于 shortKey, 其实就是我们以全限定名作为属性时, 它取得是分隔符分割后最后的一项。
// 将 key 以 . 分割, 并获取最后一项作为 shortKey private String getShortName(String key) { final String[] keyParts = key.split("\\\\."); return keyParts[keyParts.length - 1]; }

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

在 mybatis 中加入 shortKey 之后, 我们只需要写
selectList("selectAll");

但是, 在实际使用时用处不大, 很多函数基本都是会是二义性的, 不明白为何不取消。
3.3.3 Ambiguity
AmbiguityStrictMap 中的静态内部类。
protected static class Ambiguity { final private String subject; public Ambiguity(String subject) { this.subject = subject; }public String getSubject() { return subject; } }

其作用记录存在二义性的 key, 告诉使用者, 你的这个 key 是二义性的。
3.3.4 get
public V get(Object key) { // value 为空则报错 V value = https://www.songbingjia.com/android/super.get(key); if (value == null) { throw new IllegalArgumentException(name +" does not contain value for " + key); } // 二义性也报错 if (value instanceof Ambiguity) { throw new IllegalArgumentException(((Ambiguity) value).getSubject() + " is ambiguous in " + name + " (try using the full name including the namespace, or rename one of the entries)"); } // 正常情况下应该是返回 return value; }

一起学 mybatis你想不想来学习 mybatis? 学习其使用和源码呢?那么, 在博客园关注我吧!!
我自己打算把这个源码系列更新完毕, 同时会更新相应的注释。快去 star 吧!!
mybatis最新源码和注释
【mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)】
mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)

文章图片


    推荐阅读