声明式基于XML的缓存

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

<!-- 我们要使其可缓存的服务 -->
<bean id="bookService" class="x.y.service.DefaultBookService"/>

<!-- 缓存定义 -->
<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>

<!-- 将可缓存行为应用于所有BookService接口 -->
<aop:config>
	<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.BookService.*(..))"/>
</aop:config>

<!-- 缓存管理器定义已省略 -->

在上述配置中,bookService 被设置为可缓存。要应用的缓存语义封装在cache:advice 定义中,这会导致findBooks 方法用于将数据放入缓存,loadBooks 方法用于清除数据。这两个定义都针对books 缓存。

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

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