mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)
@
| 相关文章推荐 |
|---|
| 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 StrictMap
StrictMap 有什么特殊的地方, 为什么不直接用 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
Ambiguity是 StrictMap 中的静态内部类。
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 = 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源码-解析配置文件(四-1)之配置文件Mapper解析(cache)的更多相关文章
- mybatis源码分析(三)------------映射文件的解析
本篇文章主要讲解映射文件的解析过程 Mapper映射文件有哪几种配置方式呢?看下面的代码: <!-- 映射文件 --> <mappers> <!-- 通过resource ...
- MyBatis源码分析(1)-MapConfig文件的解析
1.简述 MyBatis是一个优秀的轻ORM框架,由最初的iBatis演化而来,可以方便的完成sql语句的输入输出到java对象之间的相互映射,典型的MyBatis使用的方式如下: String re ...
- MyBatis源码分析(四):SQL执行过程分析
一.获取Mapper接口的代理 根据上一节,Mybatis初始化之后,利用sqlSession(defaultSqlSession)的getMapper方法获取Mapper接口 1 @Override ...
- mybatis源码分析(四)---------------代理对象的生成
在mybatis两种开发方式这边文章中,我们提到了Mapper动态代理开发这种方式,现在抛出一个问题:通过sqlSession.getMapper(XXXMapper.class)来获取代理对象的过程 ...
- 【mybatis源码学习】mybtias基础组件-占位符解析器
一.占位符解析器源码 1.占位符解析器实现的目标 通过解析字符串中指定前后缀中的字符,并完成相应的功能. 在mybtias中的应用,主要是为了解析Mapper的xml中的sql语句#{}中的内容,识别 ...
- mybatis 源码分析(四)一二级缓存分析
本篇博客主要讲了 mybatis 一二级缓存的构成,以及一些容易出错地方的示例分析: 一.mybatis 缓存体系 mybatis 的一二级缓存体系大致如下: 首先当一二级缓存同时开启的时候,首先命中 ...
- mybatis源码学习(三):MappedStatement的解析过程
我们之前介绍过MappedStatement表示的是XML中的一个SQL.类当中的很多字段都是SQL中对应的属性.我们先来了解一下这个类的属性: public final class MappedSt ...
- mybatis源码学习(四):动态SQL的解析
之前的一片文章中我们已经了解了MappedStatement中有一个SqlSource字段,而SqlSource又有一个getBoundSql方法来获得BoundSql对象.而BoundSql中的sq ...
- mybatis源码-解析配置文件(四)之配置文件Mapper解析
在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...
随机推荐
- java中的数据类型,运算符,字符串,输入输出,控制流,大数值,数组; 《java核心技术卷i》 第三章:java基本程序结构;
<java核心技术卷i> 第三章:java基本程序结构: 每次看书,去总结的时候,总会发现一些新的东西,这次对于java的数组有了更深的了解: java中的数据类型,运算符,字符串,输入输 ...
- spring学习总结——介绍
介绍:以下博客的内容都是依据<spring实战4>这本书.spring4.0 来总结. 一.spring作用 Spring可以做很多事情,它为企业级开发提供给了丰富的功能,但是这些功能的底 ...
- CsQuery获取IDomObject元素的完整CSS选择器
一.方法说明 通过IDomObject元素,获取完整的CSS选择器,过滤HTML和BODY元素,自动将class.id添加到选择器上,优先添加class,无class再添加id.如: <html ...
- 根据class判断
一.生命不息,代码不止
- c/c++ 标准库 map set 大锅炖
标准库 map set 大锅炖 一,关联容器有哪些 按关键字有序保存元素 map 保存key和value set 只保存key mulutimap key可以重复出现 multiset key可以重复 ...
- Python 标示符和关键字
标示符 开发人员在程序中自定义的一些符号和名称.标示符是自己定义的,如变量名 .函数名等 标示符的规则 标示符由字母.下划线和数字组成,且数字不能开头 注:python中的标识符是区分大小写的 命 ...
- CentOS7 Python2 和Python3 共存(Python3安装)【转】
1.查看是否已经安装Python CentOS 7.2 默认安装了python2.7.5 因为一些命令要用它比如yum 它使用的是python2.7.5. 使用 python -V 命令查看一下是否安 ...
- Qt的事件
Qt的事件机制 事件过滤器: 可以让一个对象侦听拦截另外一个对象的事件. 实现原理: 在所有Qt对象的基类:QObject中有一个 类型为:QObjectList 名字为:eventFilters 的 ...
- java基础编程练习
1.编写程序实现对给定的 4 个整数从大到小的顺序排列. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 ...
- JavaScript -- 时光流逝(九):Window 对象、Navigator 对象
JavaScript -- 知识点回顾篇(九):Window 对象.Navigator 对象 1. Window 对象 1.1 Window 对象的属性 (1) closed: 返回窗口是否已被关闭. ...