在项目中,一般我们会把服务层(service)的一些查询结果和一些数据进行缓存。缓存的种类有很多。这里进行redis作为缓存框架,进行一个缓存的配置。配置前需要先了解一些基本的知识
在Spring中缓存主要有一个缓存接口(Cache)与缓存管理接口(CacheManager)。可以通过扩展这两个接口实现对应的缓存管理。redis就是这样。当然还有很多比如Guava等都对其进行了扩展。这里只看redis的缓存基本架构:
首先一个抽象的缓存管理类AbstractCacheManager,对CacheManager进行了基本功能的实现,这个类还实现了InitializingBean接口,这个我们知道在spring中实现这个接口就可以在类初始化完成之后,执行接口的afterPropertiesSet方法,AbstractCacheManager在这个方法中执行了initializeCaches方法,也就是初始化缓存。其代码如下:
//首先加载缓存。loadCaches是一个模板方法,具体怎么加载子类决定。
Collection<? extends Cache> caches = loadCaches();
synchronized (this.cacheMap) {
//每次初始化都创建一个新的缓存名称Set。代码最后一行,把这个set集合变成只读
this.cacheNames = Collections.emptySet();
//清空缓存Map ConcurrentHashMap
this.cacheMap.clear();
//初始化 cacheNames
//1. 循环遍历子类加载的caches
Set<String> cacheNames = new LinkedHashSet<String>(caches.size());
for (Cache cache : caches) {
String name = cache.getName();
//加入到缓存map集合中,在加入前要进行对缓存进行装配 decorateCache(cache)
//decorateCache 这个方法本身就是返回cache。但是子类
//AbstractTransactionSupportingCacheManager 重写它。这个类从名字可以看出
//是支持事务。它有一个属性transactionAware默认为false. 如果配置了支持事务,
//就会把当前cache装配成支持事物的cache 所以后面会有支持事务的配置,配置的就是
//transactionAware 这个属性为true
//TransactionAwareCacheDecorator
this.cacheMap.put(name, decorateCache(cache));
//2. 把cache的name加入到name集合中
cacheNames.add(name);
}
//set变成只读
this.cacheNames = Collections.unmodifiableSet(cacheNames);
}
}
初始化缓存之后,也实现了基本的获取缓存方法:
public Cache getCache(String name) {
//根据缓存name直接从自己的cache map中获取
Cache cache = this.cacheMap.get(name);
if (cache != null) {
return cache;
}
else {
//如果没有,那么就同步创建
synchronized (this.cacheMap) {
//这里再一次获取,避免在同步前,有线程已经添加进去了。
cache = this.cacheMap.get(name);
if (cache == null) {
//如果还没有,就调用getMissingCache方法获取。
//这个方法可以看作一个模板方法,只不过自己实现了返回null
//也就是说默认不创建。子类可以通过重写这个方法进行创建。
cache = getMissingCache(name);
if (cache != null) {
//对创建的cache进行装配
cache = decorateCache(cache);
//放入缓存 map中
this.cacheMap.put(name, cache);
//更新缓存名称集合。 上面我们知道缓存名称集合被修改成只读,
//所以更新方法里面是创建一个新的,然后size进行加1,再把前面的
//添加进去,然后加入新建的这个,再修改成只读
updateCacheNames(name);
}
}
return cache;
}
}
}
当然你也可以直接调用lookupCache方法,该方法就是直接获取。没有后续的步骤