首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

源代码解读基于Spring的宣言性缓存实现原理

2012-10-07 
源代码解读基于Spring的声明性缓存实现原理前言: 本贴复制来源:http://www.blogjava.net/xmatthew/archive

源代码解读基于Spring的声明性缓存实现原理
前言:
本贴复制来源:http://www.blogjava.net/xmatthew/archive/2010/05/archive/2010/04/22/319146.html
  本文档将讲解一下,如何借助Spring Module项目,实现配置声明性缓存功能。

   声明式缓存配置有效地将缓存功能从应用程序的核心需求中分离出来,解决了上文提及的众多问题,还带来了以下优点:
更明晰的责任分离。系统中的模块仅负责其核心需求,不再负责缓存功能。这将带来更出色的可追溯性。
更高的模块化程度。将缓存功能从核心模块中分离出来减少了重复代码(支持“一次且仅一次”原则),并有助于避免代码混乱。
设计决策的后期绑定。使用声明式缓存,开发人员可将与缓存实现和调优有关的决策制订延后。开发人员可将精力集中在应用程序的当前核心需求上。声明式配置支持 YAGNI(“you aren't gonna need it”的缩写,意为“您将不会需要它)原则,仅在开发人员确实需要的时候才允许他们为应用程序添加缓存,而且不需要进行系统级的更改。

说明:
  本档的配置经过本人测试,都能正确运行。
  运行环境: Jdk5.0, Spring-2.5, Spring-modules-0.9, ehcache-1.6.0-beta4.jar

首先创建一个StudentService服务类,本文将对其所有的以get* 方式命令的方法,进行缓存处理。当调用set* 命令时,需要其删除缓存
以更做数据的更新。 
源代码如下:



接下来,就是编写Spring配置文件 context.xml,以实现根据上面的要求,进行声明性缓存功能的配置

Spring的配置内容如下:(已加上注释)


下面将要测试配置是否能正确工作,编写一个测试类 Test.java内容如下:


  

从类图中,可以看到AbstractCachingInterceptor抽象实现了MethodInterceptor接口的invoke方法。这也是整个缓存处理的入口。
看代码之前,我先来补充一下框架是如果实现方法拦截后的匹配过程。
首先是构建匹配规则:
由 MethodMapCachingInterceptor类的onAfterPropertiesSet方法实现。
实现思路如下:
取得 cachingModels属性,遍历每一个 key
例如上例中 StudentService.get* , 解析出 class 类名(StudentService),和方法的匹配字符串(get*)
然后通过 Class.forName 方法,装载该类,取出该类的所有方法,一一与指定的方法匹配字符串进行 正则匹配TextMatcher.isMatch,匹配通过的则放入到一个Map中, key=Method对象, value=CacheModel对象当 拦截器 对调用的方法进行拦截时,通过 map.get返回值来确认是否对方法进行缓存处理

实现代码如下:已经添加注释
 1     public final Object invoke(MethodInvocation mi) throws Throwable { 2         Method method = mi.getMethod();//取得拦截的方法 3         if (!CachingUtils.isCacheable(method)) 4             return methodNotCacheable(mi, method); //如果是void返回值,则不需要缓存支持 5  6         CachingModel model = model(mi); //根据method,则定是否要进行缓存 7         if (model == null) return noModelFound(mi, method); 8  9         Serializable key = keyGenerator.generateKey(mi);//根据方法对象,生成key10         Object cached = cache.getFromCache(key, model);//如果有缓存11 12         if (null == cached) return cachedValueFromSource(mi, key, model); //如果没有缓存,把返回保存到缓存13         return unmaskNull(cached);14     }


到些基本的实现流程已经讲解完了,其它的大家可以通过阅读源代码进行理解。

最后补充一下如何根据这个框架集成其它的缓存服务,需要实现的接口和继承的抽象类如下:
AbstractCacheProviderFacade 缓存保存,取得,更新的实现
AbstractCacheModelValidator 检测缓存模型合法性
CachingModel 保存缓存的模型接口
AbstractFlushingModel 刷新缓存的模型抽象类


Good Luck!
Yours Matthew!


热点排行