Hibernate老鸟的话,对于Hibernate cache的精妙实现应该都是非常了解,即便不了解其实现原理,也知道Hibernate cache非常的易用,集成EhCache,对于系统性能也有很好的提升。那我们来看看如易云的框架,如易云的框架基于Mybatis,Mybatis新版本中也集成了cache,并且也有开源的分布式cache集成(例如: Mybatis-Ignite https://github.com/mybatis/ignite-cache ),但如易云在数据库操作方面做了非常多的业务语义抽象(具体参见: 创易-数据库层设计 ),对于cache,当然一方面我希望在这个层面做下处理,另一方面就是 我之前在上家公司基于spring cache做的独有的两层cache(JVM+分布式cache,对开发人员透明,框架自动具备这样的能力 【这个以后的文章再表】),所以我们需要基于框架量身定做cache的集成。
说到这里,不得不由衷的佩服spring boot确实不错,以前我还要基于spring cache 把guava cache和redis装进去,现在基于spring boot的 autoconfigure的cache封装,就可以很方便把这些用起来,关于 springboot的cache使用,请参见:http://www.jianshu.com/p/64f684bd0ce9 但麻烦的地方在于,我们的框架+代码自动生成,在整个体系里,默认的实现都在abstract抽象类,那么它只能做一次cacheNames的配置, 如果设置 cacheEvict(allEntries=true),会做全局的失效,而正常是这个模型内的缓存失效,好在 可以自定义 CacheResolver。
运行期动态设置cacheNames
不过自定义的CacheResolver,需要注入cacheManager, 而cacheManager不能注入成功, 最终 使用 @Lazy,懒加载,并且 在spring boot应用启动时 将ApplicationContext 设置给ApplicationContextHolder,在 需要的时候获取到cachemanager设置给CacheResolver, 具体代码:
@Component("runtimeImplCacheResolver")
@Lazy
public classRuntimeImplCacheResolverextendsAbstractCacheResolver {
privateApplicationContextctx;
publicRuntimeImplCacheResolver() {
//super.setCacheManager(SpringContextHolder.getApplicationContext().getBean(CacheManager.class));
}
@PostConstruct
public voidinit(){
super.setCacheManager(SpringContextHolder.getApplicationContext().getBean(CacheManager.class));
}
@Override
protectedCollection getCacheNames(CacheOperationInvocationContext context) {
if(context.getOperation().getCacheNames().contains("SECOMMONDYN")){
Set cacheName =newHashSet();
context.getTarget().getClass().toString();
String simpleName = context.getTarget().getClass().getSimpleName();
simpleName = simpleName.substring(0, simpleName.length() -11);
cacheName.add(simpleName);
returncacheName;
}else{
returncontext.getOperation().getCacheNames();
}
}
}
框架调用: