2019独角兽企业重金招聘Python工程师标准>>>
二级缓存与一级缓存机制相同,不同的是它的作用域是在Mapper层, 即不同会话之间共享缓存内容,二级缓存不是默认开启的,如果配置了cache功能在创建Executor后会装饰一层CachingExecutor,存取二级缓存都在CachingExecutor中封装,总体缓存架构图见https://my.oschina.net/chengxiaoyuan/blog/792878
一、二级缓存使用
全局配置
Mapper里面配置cache
如果想mapper中某个查询不用二级缓存则配置useCache=“false”
如果希望每次执行sql前都刷新缓存则配置flushCache="true",该值select类型默认为false, 其他为true
二、二级缓存构造
上面cache里面有几个参数配置:
public class XMLMapperBuilder extends BaseBuilder {
private void cacheElement(XNode context) throws Exception {
if (context != null) {
//获取缓存类型, 默认内存map, PERPETUAL在configuration初始化的时候会注册对应PerpetualCache
String type = context.getStringAttribute("type", "PERPETUAL");
//获取class,如果该类型不是自带的会使用classLoader加载
Class extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
//回收策略,装饰上面的缓存, 默认LRU
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);
//标签下面的参数
Properties props = context.getChildrenAsProperties();
//通过上面的参数构造cache
builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, props);
}
}
}
PERPETUAL、LRU这些简称在初始化的时候会注册:
public Configuration() {
.......
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
typeAliasRegistry.registerAlias("LRU", LruCache.class);
typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
......
}
上面去的各种参数后通过builderAssistant构造缓存并放到configuration配置的map中,看builderAssistant.useNewCache代码:
public Cache useNewCache(Class extends Cache> typeClass, Class extends Cache> evictionClass, Long flushInterval,
Integer size, boolean readWrite, Properties props) {
//判断为空则取默认
typeClass = valueOrDefault(typeClass, PerpetualCache.class);
evictionClass = valueOrDefault(evictionClass, LruCache.class);
//创建cache, 这里是builder模式, currentNamespace为id
Cache cache = new CacheBuilder(currentNamespace).implementation(typeClass).addDecorator(evictionClass)
.clearInterval(flushInterval).size(size).readWrite(readWrite).properties(props).build();
//放到configuration里的map中, key为cache的id
configuration.addCache(cache);
currentCache = cache;
return cache;
}
最终通过缓存的构造模式构造一个缓存,并把缓存放入到configuration的map中,看CacheBuilder
public Cache build() {
//判断缓存内部实现和装饰是否为空,如果为空则再给默认值
setDefaultImplementations();
//创建缓存实现
Cache cache = newBaseCacheInstance(implementation, id);
//properties配置
setCacheProperties(cache);
//如果是内部map缓存则用内部装饰
if (PerpetualCache.class.equals(cache.getClass())) {
for (Class extends Cache> decorator : decorators) {
cache = newCacheDecoratorInstance(decorator, cache);
setCacheProperties(cache);
}
cache = setStandardDecorators(cache);
} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
//如果是LoggingCache子类则用LoggingCache装饰
cache = new LoggingCache(cache);
}
return cache;
}
三、接入第三方缓存
导入依赖包
net.sf.ehcache
ehcache-core
2.6.5
org.mybatis.caches
mybatis-ehcache
1.0.2
ehcache自带配置
mybatis中mapper配置