在上一篇中我们找到了Mapper.xml文件的入口,在入口中主要是解析各种标签,这节我们看看mybatis如何解析cache标签。
cache-ref
解析cache-ref主要是在XMLMapperBuilder的cacheRefElement方法中,下面我们来看看这个方法
private void cacheRefElement(XNode context) {
if (context != null) {
//在一步我也不知道做什么用的
configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant,
context.getStringAttribute("namespace"));
try {
cacheRefResolver.resolveCacheRef();
} catch (IncompleteElementException e) {
configuration.addIncompleteCacheRef(cacheRefResolver);
}
}
}
cacheRefResolver.resolveCacheRef();
中什么也没做,直接调用了MapperBuilderAssistant.useCacheRef
方法。
下面我们看看useCacheRef方法的内容(仅仅展示关键代码)
public Cache useCacheRef(String namespace) {
unresolvedCacheRef = true;
Cache cache = configuration.getCache(namespace);
if (cache == null) {
throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
}
currentCache = cache;
unresolvedCacheRef = false;
return cache;
}
解析cache-ref标签,主要是通过cache-ref标签中namespace属性,获取关于cache的对象。(为什么不把真正的cache保存起来,如果不保存起来如何使用呢?)
cache
下面我们看看cache标签的解析,解析cache主要是在XMLMapperBuilder.cacheElement
方法中
private void cacheElement(XNode context) throws Exception {
String type = context.getStringAttribute("type", "PERPETUAL");
Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
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);
boolean blocking = context.getBooleanAttribute("blocking", false);
Properties props = context.getChildrenAsProperties();
builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
}
首先在cache标签中,获取了cache中的各种属性,获取完各种属性后,调用了MapperBuilderAssistant.useCache
方法。
下面我们看看MapperBuilderAssistant.useCache
方法
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.addCache(cache);
currentCache = cache;
return cache;
}
前面6个参数,是cache标签中我们关于缓存的一些属性。最后一个参数props是cache标签中,property标签中的属性值的集合。前面6个参数主要是用来初始化Mybatis的cache对象。但是对于我们自定义的缓存对象,Mybatis并不知道应该如何初始化该缓存对象。那么我们可以在property中设置关于我们自己的缓存参数。例如:
public class CustomCache implements Cache {
private int size;
private int flush;
}
那我们配置的cache标签如下:
<cache type = 'CustomCache' .... >
<property name='size' value = '10'></property>
...
</cache>
这节我们看到了,Mybatis是如何解析cache标签的。Mybatis把cache标签解析映射成了Cache对象。
然后把cache添加到Configuration中的caches中key:mapper.xml的namespace,value:cache对象。