Declarative XML-based Caching

如果注释不是一种选择(可能是因为无法访问源或外部代码),您可以使用 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 缓存进行操作。

通过使用 AspectJ 切点表达式(更多信息可在Aspect Oriented Programming with Spring中找到),`aop:config`定义将缓存建议应用到程序中的适当点。在前面的示例中,将会考虑 `BookService`中的所有方法并将缓存建议应用于它们。

声明性 XML 缓存支持所有基于注释的模型,因此在两者之间移动应该相当容易。此外,两者都可以用在同一个应用程序中。基于 XML 的方法不会影响目标代码。但是,它本质上更加冗长。在处理针对缓存的超载方法的类时,识别正确的方法需要额外的努力,因为 method 参数不是一个好鉴别器。在这些情况下,您可以使用 AspectJ 切入点来选择目标方法并应用适当的缓存功能。但是,通过 XML,可以更容易地应用包或组或接口范围的缓存(同样,由于 AspectJ 切入点),并创建类似模板的定义(就像我们在前面的示例中通过 cache:definitions``cache 属性定义目标缓存所做的那样)。