基于声明性XML的缓存
如果注解不可用(可能是因为无法访问源代码或没有外部代码),可以使用XML进行声明式缓存。因此,无需为缓存注解方法,可以外部指定目标方法和缓存指令(类似于声明式事务管理advice)。上一节中的示例可以转换为以下示例
<!-- the service we want to make cacheable -->
<bean id="bookService" class="x.y.service.DefaultBookService"/>
<!-- cache definitions -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="books">
<cache:cacheable method="findBook" key="#isbn"/>
<cache:cache-evict method="loadBooks" all-entries="true"/>
</cache:caching>
</cache:advice>
<!-- apply the cacheable behavior to all BookService interfaces -->
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.BookService.*(..))"/>
</aop:config>
<!-- cache manager definition omitted -->
在前面的配置中,bookService
被设置为可缓存的。要应用的缓存语义封装在cache:advice
定义中,这导致findBooks
方法用于将数据放入缓存,而loadBooks
方法用于驱逐数据。这两个定义都针对books
缓存。
aop:config
定义使用AspectJ切点表达式将缓存建议应用于程序中的适当点(更多信息可在Spring的面向切面编程中找到)。在前面的示例中,考虑了BookService
中的所有方法,并将缓存建议应用于它们。
声明式XML缓存支持所有基于注解的模型,因此在两者之间移动应该相当容易。此外,两者都可以在同一个应用程序中使用。基于XML的方法不会触及目标代码。但是,它本质上更冗长。当处理具有针对缓存的目标方法的重载方法的类时,识别正确的方法需要额外的工作,因为method
参数不是一个好的区分符。在这种情况下,可以使用AspectJ切点来挑选目标方法并应用相应的缓存功能。但是,通过XML,更容易应用包级、组级或接口级的缓存(同样,由于AspectJ切点),并创建模板式定义(如我们在前面的示例中通过定义cache:definitions
的cache
属性来定义目标缓存那样)。