使用 Spring 的缓存抽象时,最为通用的方式就是在方法上添加 @Cacheable 和 @CacheEvict 注解。在本章中,大多数内容都会使用这种类型的声明式注解。在 13.3 小节中,我们会看到如何使用 XML 来声明缓存边界。
在往 bean 上添加缓存注解之前,必须要启用 Spring 对注解驱动缓存的支持。如果我们使用 Java 配置的话,那么可以在其中的一个配置类上添加 @EnableCaching,这样的话就能启用注解驱动的缓存。程序清单 13.1 展现了如何实际使用 @EnableCaching。
程序清单 13.1 通过使用 @EnableCaching 启用注解驱动的缓存
package spittr.config;
import net.sf.ehcache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
@Configuration
@EnableCaching
public class CachingConfig {
@Bean
public EhCacheCacheManager cacheManager(CacheManager cm) {
return new EhCacheCacheManager(cm);
}
}
程序清单 13.1 通过使用 @EnableCaching 启用注解驱动的缓存如果以 XML 的方式配置应用的话,那么可以使用 Spring cache 命名空间中的 <cache:annotation-driven> 元素来启用注解驱动的缓存。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache
http://www.springframework.org/schema/cache/spring-cache.xsd" >
<cache:annotation-driven />
<bean id="cacheManager" class="org.springframework.cache.concurrent.ConcurrentMapCacheManager" />
</beans>
其实在本质上,@EnableCaching 和 <cache:annotation-driven> 的工作方式是相同的。它们都会创建一个切面(aspect)并触发 Spring 缓存注解的切点(pointcut)。根据所使用的注解以及缓存的状态,这个切面会从缓存中获取数据,将数据添加到缓存之中或者从缓存中移除某个值。
在程序清单 13.1 和程序清单 13.2 中,你可能已经注意到了,它们不仅仅启用了注解驱动的缓存,还声明了一个缓存管理器(cache manager)的 bean。缓存管理器是 Spring 缓存抽象的核心,它能够与多个流行的缓存实现进行集成。
在本例中,声明了 ConcurrentMapCacheManager,这个简单的缓存管理器使用java.util.concurrent.ConcurrentHashMap 作为其缓存存储。它非常简单,因此对于开发、测试或基础的应用来讲,这是一个很不错的选择。但它的缓存存储是基于内存的,所以它的生命周期是与应用关联的,对于生产级别的大型企业级应用程序, 这可能并不是理想的选择。