Spring 3.1内置了五个缓存管理器实现,如下所示:
- SimpleCacheManager
- NoOpCacheManager
- ConcurrentMapCacheManager
- CompositeCacheManager
- EhCacheCacheManager
Spring 3.2引入了另外一个缓存管理器,这个管理器可以用在基于
JCache(JSR-107)的缓存提供商之中。除了核心的Spring框架,
Spring Data又提供了两个缓存管理器:
在为Spring的缓存抽象选择缓存管理器时,我们有很
多可选方案。具体选择哪一个要取决于想要使用的底层缓存供应商。
每一个方案都可以为应用提供不同风格的缓存
Ehcache是最为流行的缓存供应商之一。Ehcache网站上说它是“Java领
域应用最为广泛的缓存”。鉴于它的广泛采用,Spring提供集成
Ehcache的缓存管理器是很有意义的。这个缓存管理器也就
是EhCacheCacheManager。
package com.lf.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;
/**
* Created by LF on 2017/5/9.
*/
@Configuration
@EnableCaching
public class MyEhCacheManage {
@Bean
public EhCacheCacheManager getCaCheManage(CacheManager cm) {
return new EhCacheCacheManager(cm);
}
@Bean
public EhCacheManagerFactoryBean regist() {
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("配置文件的文章"));
return ehCacheManagerFactoryBean;
}
}
cacheManager()方法创建了一
个EhCacheCacheManager的实例,这是通过传入Ehcache
CacheManager实例实现的.
这是因为Spring和EhCache都定义了CacheManager
类型。需要明确的是,EhCache的CacheManager要被注入到Spring
的EhCacheCacheManager(Spring CacheManager的实现)之
中。
我们需要使用EhCache的CacheManager来进行注入,所以必须也要
声明一个CacheManager bean。为了对其进行简化,Spring提供了
EhCacheManager-FactoryBean来生成EhCache的
CacheManager。方法ehcache()会创建并返回一
个EhCacheManagerFactoryBean实例。因为它是一个工厂
bean(也就是说,它实现了Spring的FactoryBean接口),所以注册
在Spring应用上下文中的并不是EhCacheManagerFactoryBean的
实例,而是CacheManager的一个实例,因此适合注入
到EhCacheCacheManager之中。
package com.lf.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
/**
* Created by LF on 2017/5/9.
*/
@Configuration
@EnableCaching
public class MyRedisCacheManage {
@Bean
public CacheManager getCaCheManage(RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
@Bean
public RedisConnectionFactory getRedisConnectionFactory(){
JedisConnectionFactory factory = new JedisConnectionFactory();
return factory;
}
@Bean
public RedisTemplate getRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
package com.lf.config;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.*;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Configuration;
/**
* Created by LF on 2017/5/8.
*/
@Configuration
@EnableCaching
public class Config implements CachingConfigurer {
@Override
public CacheManager cacheManager() {
return new SimpleCacheManager();
}
@Override
public CacheResolver cacheResolver() {
return new SimpleCacheResolver();
}
@Override
public KeyGenerator keyGenerator() {
return new SimpleKeyGenerator();
}
@Override
public CacheErrorHandler errorHandler() {
return new SimpleCacheErrorHandler();
}
}
其名字已经暗示了其是Cache解析器,用于根据实际情况来动态解析使用哪个Cache,如:
public class MyCacheResolver implements CacheResolver {
@Autowired
private CacheManager cacheManager;
@Override
public Collection extends Cache> resolveCaches(CacheOperationInvocationContext> context) {
List caches = new ArrayList();
for(String cacheName : context.getOperation().getCacheNames()) {
caches.add(cacheManager.getCache(cacheName));
}
if(context.getTarget() instanceof UserService2) {
caches.add(cacheManager.getCache("user2"));
caches.add(cacheManager.getCache("user3"));
}
return caches;
}
}
context中存放了当前cache的操作类型、目标对象、目标方法、参数信息,这样我们可以根据这些信息来决定使用那些cache; context.getOperation().getCacheNames()得到当前目标对象/目标方法上配置的cache Name;然后我们可以在此基础上添加额外的cache。
此处需要注意的是即使配置了CacheResolver,也必须在@CacheConfig或方法上的如@CachePut上指定至少一个Cache Name。
用于捕获从Cache中进行CRUD时的异常的回调处理器。
我们并不是只能有且仅有一个缓存管理器。如果你很难确定该使用哪
个缓存管理器,或者有合法的技术理由使用超过一个缓存管理器的
话,那么可以尝试使用Spring的CompositeCacheManager。
CompositeCacheManager要通过一个或更多的缓存管理器来进行
配置,它会迭代这些缓存管理器,以查找之前所缓存的值。以下的程
序清单展现了如何创建CompositeCacheManager bean,它会迭代
JCacheCacheManager、EhCacheCache-Manager和
RedisCacheManager。
@Bean
public CacheManager getCaCheManage(RedisTemplate redisTemplate) {
CompositeCacheManager cacheManager = new CompositeCacheManager();
List list =new ArrayList<>();
list.add(CacheManager1)
list.add(CacheManager2)
list.add(CacheManager3)
cacheManager.setCacheManagers(list);
return cacheManager;
}
当查找缓存条目时,CompositeCacheManager首先会从
CacheManager1开始检查CacheManager1实现,然后通过
CacheManager2检查CacheManager2,最后会使
用CacheManager3来检查CacheManager3,完成缓存条目的查找。
在配置完缓存管理器并启用缓存后,就可以在bean方法上应用缓存规
则了。让我们看一下如何使用Spring的缓存注解来定义缓存边界。