- 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);
- }
- }
- // PerpetualCache.class 为 org.apache.ibatis.cache.impl.PerpetualCache
- typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
- 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;
- }
- 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;
- }
- public void addCache(Cache cache) {
- caches.put(cache.getId(), cache);
- }
- 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.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
- // 将 key 以 . 分割, 并获取最后一项作为 shortKey
- private String getShortName(String key) {
- final String[] keyParts = key.split("\\.");
- return keyParts[keyParts.length - 1];
- }
- protected static class Ambiguity {
- final private String subject;
- public Ambiguity(String subject) {
- this.subject = subject;
- }
- public String getSubject() {
- return subject;
- }
- }
- 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;
- }
来源: https://www.cnblogs.com/homejim/p/9743921.html