跳到主要内容

基于 XML 的声明式缓存

ChatGPT-4o 中英对照 Declarative XML-based Caching

如果无法使用注解(可能是因为无法访问源代码或没有外部代码),可以使用 XML 进行声明式缓存。因此,不是通过注解方法进行缓存,而是可以在外部指定目标方法和缓存指令(类似于声明式事务管理建议)。上一节的示例可以转换为以下示例:

<!-- 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 -->
xml

在前面的配置中,bookService 被设置为可缓存。要应用的缓存语义封装在 cache:advice 定义中,这导致 findBooks 方法用于将数据放入缓存,而 loadBooks 方法用于驱逐数据。这两个定义都作用于 books 缓存。

aop:config 定义通过使用 AspectJ 切入点表达式将缓存通知应用于程序中的适当点(更多信息请参见 Spring 的面向切面编程)。在前面的示例中,BookService 的所有方法都被考虑,并且缓存通知被应用于它们。

声明式 XML 缓存支持所有基于注解的模型,因此在两者之间切换应该相当容易。此外,它们都可以在同一个应用程序中使用。基于 XML 的方法不会接触目标代码。然而,它本质上更为冗长。当处理具有重载方法且这些方法需要缓存的类时,识别正确的方法确实需要额外的努力,因为 method 参数不是一个好的区分器。在这些情况下,你可以使用 AspectJ 切入点来精确选择目标方法并应用适当的缓存功能。然而,通过 XML,更容易应用包、组或接口范围的缓存(同样由于 AspectJ 切入点)并创建类似模板的定义(就像我们在前面的例子中通过 cache:definitions cache 属性定义目标缓存一样)。