请先看
https://my.oschina.net/u/3866531/blog/1840386
CompositeCacheManager类****
Composite,混合的,混成的
Spring提供CompositeCacheManager的主要目的就是为了混合使用多种缓存时进行管理。
一、实际测试--CompositeCacheManager中打断点****
断点打在getCache上****
GuavaDataCache源码--去掉类上的******@CacheConfig(cacheManager = "guavaCacheManager")**注解
package com.ding.data.cache;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
//@CacheConfig(cacheManager = "guavaCacheManager")
public class GuavaDataCache {
private Map<Long, String> dataMap = new HashMap<Long, String>();
/**
* 初始化
*/
@PostConstruct
public void init() {
dataMap.put(1L, "张三");
dataMap.put(2L, "李四");
dataMap.put(3L, "王五");
}
/**
* 查询
* 如果数据没有缓存,那么从dataMap里面获取,如果缓存了,
* 那么从guavaDemo里面获取
* 并且将缓存的数据存入到 guavaDemo里面
* 其中key 为 #id+dataMap
*/
@Cacheable(value="guavaDemo" ,key="#id + 'dataMap'")
public String query(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : query id is " + id);
return dataMap.get(id);
}
/**
* 插入 或者更新
* 插入或更新数据到dataMap中
* 并且缓存到 guavaDemo中
* 如果存在了那么更新缓存中的值
* 其中key 为 #id+dataMap
*/
@CachePut(value="guavaDemo" ,key="#id + 'dataMap'")
public String put(Long id, String value) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);
dataMap.put(id, value);
// data persistence
return value;
}
/**
* 删除
* 删除dataMap里面的数据
* 并且删除缓存guavaDemo中的数据
* 其中key 为 #id+dataMap
*/
@CacheEvict(value="guavaDemo" , key="#id + 'dataMap'")
public void remove(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : remove id is "+ id + " data");
dataMap.remove(id);
// data remove
}
}
RedisDataCache源码--去掉类上的******@CacheConfig(cacheManager = "redisCacheManager")**注解
package com.ding.data.cache;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
//@CacheConfig(cacheManager = "redisCacheManager")
public class RedisDataCache {
private Map<Long, String> dataMap = new HashMap<Long, String>();
/**
* 初始化
*/
@PostConstruct
public void init() {
dataMap.put(1L, "111");
dataMap.put(2L, "222");
dataMap.put(3L, "333");
}
/**
* 查询
* 如果数据没有缓存,那么从dataMap里面获取,如果缓存了,
* 那么从guavaDemo里面获取
* 并且将缓存的数据存入到 guavaDemo里面
* 其中key 为 #id+dataMap
*/
@Cacheable(value="redisDemo" ,key="#id + 'dataMap'")
public String query(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : query id is " + id);
return dataMap.get(id);
}
/**
* 插入 或者更新
* 插入或更新数据到dataMap中
* 并且缓存到 guavaDemo中
* 如果存在了那么更新缓存中的值
* 其中key 为 #id+dataMap
*/
@CachePut(value="redisDemo" ,key="#id + 'dataMap'")
public String put(Long id, String value) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);
dataMap.put(id, value);
// data persistence
return value;
}
/**
* 删除
* 删除dataMap里面的数据
* 并且删除缓存guavaDemo中的数据
* 其中key 为 #id+dataMap
*/
@CacheEvict(value="redisDemo" , key="#id + 'dataMap'")
public void remove(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : remove id is "+ id + " data");
dataMap.remove(id);
// data remove
}
}
访问http://localhost:8080/get?id=1,进入断点,看到如下
访问http://localhost:8080/getr?id=1,进入断点,看到如下
所以可见此时是通过CompositeCacheManager进行管理的,CacheConfig类中的CompositeCacheManager** 起作用了**
package com.ding.data.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cache.CacheManager;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.cache.support.CompositeCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
@Configuration
public class CacheConfig implements ApplicationRunner {
@Resource
private List<CacheManager> cacheManagers;
public void run(ApplicationArguments args) throws Exception {
System.out.println("CacheManager大小为=========" + cacheManagers.size());
System.out.println("=================================================");
for(CacheManager c:cacheManagers){
System.out.println(c.getCacheNames());
}
}
@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(
RedisTemplate<Object, Object> redisTemplate) {
redisTemplate.setKeySerializer(new StringRedisSerializer());
RedisCacheManager redisCacheManager = new RedisCacheManager(
redisTemplate);
redisCacheManager.setCacheNames(Arrays.asList("redisDemo"));
redisCacheManager.setUsePrefix(true);
return redisCacheManager;
}
@Bean(name = "guavaCacheManager")
public GuavaCacheManager getGuavaCacheManager() {
GuavaCacheManager guavaCacheManager = new GuavaCacheManager();
guavaCacheManager.setCacheBuilder(CacheBuilder.newBuilder()
.expireAfterWrite(3600, TimeUnit.SECONDS).maximumSize(1000));
ArrayList<String> guavaCacheNames = Lists.newArrayList();
guavaCacheNames.add("guavaDemo");
guavaCacheManager.setCacheNames(guavaCacheNames);
return guavaCacheManager;
}
@Bean(name = "cacheManager")
@Primary
public CompositeCacheManager cacheManager(
RedisCacheManager redisCacheManager,
GuavaCacheManager guavaCacheManager) {
CompositeCacheManager cacheManager = new CompositeCacheManager(
redisCacheManager, guavaCacheManager);
return cacheManager;
}
}
二、实际测试--CompositeCacheManager中打断点****
断点打在getCache上****
GuavaDataCache源码--加上类上的******@CacheConfig(cacheManager = "guavaCacheManager")**注解
package com.ding.data.cache;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@CacheConfig(cacheManager = "guavaCacheManager")
public class GuavaDataCache {
private Map<Long, String> dataMap = new HashMap<Long, String>();
/**
* 初始化
*/
@PostConstruct
public void init() {
dataMap.put(1L, "张三");
dataMap.put(2L, "李四");
dataMap.put(3L, "王五");
}
/**
* 查询
* 如果数据没有缓存,那么从dataMap里面获取,如果缓存了,
* 那么从guavaDemo里面获取
* 并且将缓存的数据存入到 guavaDemo里面
* 其中key 为 #id+dataMap
*/
@Cacheable(value="guavaDemo" ,key="#id + 'dataMap'")
public String query(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : query id is " + id);
return dataMap.get(id);
}
/**
* 插入 或者更新
* 插入或更新数据到dataMap中
* 并且缓存到 guavaDemo中
* 如果存在了那么更新缓存中的值
* 其中key 为 #id+dataMap
*/
@CachePut(value="guavaDemo" ,key="#id + 'dataMap'")
public String put(Long id, String value) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);
dataMap.put(id, value);
// data persistence
return value;
}
/**
* 删除
* 删除dataMap里面的数据
* 并且删除缓存guavaDemo中的数据
* 其中key 为 #id+dataMap
*/
@CacheEvict(value="guavaDemo" , key="#id + 'dataMap'")
public void remove(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : remove id is "+ id + " data");
dataMap.remove(id);
// data remove
}
}
RedisDataCache源码--去掉类上的******@CacheConfig(cacheManager = "redisCacheManager")**注解
package com.ding.data.cache;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.PostConstruct;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
@Service
@CacheConfig(cacheManager = "redisCacheManager")
public class RedisDataCache {
private Map<Long, String> dataMap = new HashMap<Long, String>();
/**
* 初始化
*/
@PostConstruct
public void init() {
dataMap.put(1L, "111");
dataMap.put(2L, "222");
dataMap.put(3L, "333");
}
/**
* 查询
* 如果数据没有缓存,那么从dataMap里面获取,如果缓存了,
* 那么从guavaDemo里面获取
* 并且将缓存的数据存入到 guavaDemo里面
* 其中key 为 #id+dataMap
*/
@Cacheable(value="redisDemo" ,key="#id + 'dataMap'")
public String query(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : query id is " + id);
return dataMap.get(id);
}
/**
* 插入 或者更新
* 插入或更新数据到dataMap中
* 并且缓存到 guavaDemo中
* 如果存在了那么更新缓存中的值
* 其中key 为 #id+dataMap
*/
@CachePut(value="redisDemo" ,key="#id + 'dataMap'")
public String put(Long id, String value) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : add data ,id is "+ id);
dataMap.put(id, value);
// data persistence
return value;
}
/**
* 删除
* 删除dataMap里面的数据
* 并且删除缓存guavaDemo中的数据
* 其中key 为 #id+dataMap
*/
@CacheEvict(value="redisDemo" , key="#id + 'dataMap'")
public void remove(Long id) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(sdf.format(new Date()) + " : remove id is "+ id + " data");
dataMap.remove(id);
// data remove
}
}
访问http://localhost:8080/get?id=1,没进入断点
访问http://localhost:8080/getr?id=1,没进入断点
所以可见,此时因为标注上了 @CacheConfig(cacheManager =** "guavaCacheManager"******)** 和 @CacheConfig(cacheManager = "redisCacheManager"******)** ,所以直接就知道需要用哪个CacheManager了,不需要CompositeCacheManager去匹配了**
直接去掉CacheConfig类中的CompositeCacheManager** ,在不同的缓存上加上 @CacheConfig(cacheManager = "guavaCacheManager"******)** 和 @CacheConfig(cacheManager = ****"redisCacheManager"********)**,是否可以?——测试一下
此时的CacheConfig类代码
package com.ding.data.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cache.CacheManager;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
@Configuration
public class CacheConfig implements ApplicationRunner {
@Resource
private List<CacheManager> cacheManagers;
public void run(ApplicationArguments args) throws Exception {
System.out.println("CacheManager大小为=========" + cacheManagers.size());
System.out.println("=================================================");
for(CacheManager c:cacheManagers){
System.out.println(c.getCacheNames());
}
}
@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(
RedisTemplate<Object, Object> redisTemplate) {
redisTemplate.setKeySerializer(new StringRedisSerializer());
RedisCacheManager redisCacheManager = new RedisCacheManager(
redisTemplate);
redisCacheManager.setCacheNames(Arrays.asList("redisDemo"));
redisCacheManager.setUsePrefix(true);
return redisCacheManager;
}
@Bean(name = "guavaCacheManager")
public GuavaCacheManager getGuavaCacheManager() {
GuavaCacheManager guavaCacheManager = new GuavaCacheManager();
guavaCacheManager.setCacheBuilder(CacheBuilder.newBuilder()
.expireAfterWrite(3600, TimeUnit.SECONDS).maximumSize(1000));
ArrayList<String> guavaCacheNames = Lists.newArrayList();
guavaCacheNames.add("guavaDemo");
guavaCacheManager.setCacheNames(guavaCacheNames);
return guavaCacheManager;
}
// @Bean(name = "cacheManager")
// @Primary
// public CompositeCacheManager cacheManager(
// RedisCacheManager redisCacheManager,
// GuavaCacheManager guavaCacheManager) {
// CompositeCacheManager cacheManager = new CompositeCacheManager(
// redisCacheManager, guavaCacheManager);
// return cacheManager;
// }
}
结果启动时就报错了
java.lang.IllegalStateException: No CacheResolver specified, and no unique bean of type CacheManager found. Mark one as primary (or give it the name 'cacheManager') or declare a specific CacheManager to use, that serves as the default one.
at org.springframework.cache.interceptor.CacheAspectSupport.afterSingletonsInstantiated(CacheAspectSupport.java:186) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:792) ~[spring-beans-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.6.RELEASE.jar:4.2.6.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:766) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.createAndRefreshContext(SpringApplication.java:361) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1191) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1180) [spring-boot-1.3.5.RELEASE.jar:1.3.5.RELEASE]
at com.ding.data.App.main(App.java:33) [classes/:na]
上面报错是因为Spring Context 中存在多个实现了 CacheManager.class 的 Bean,需要使用 @Primary 注解指定优先选择的 CacheManager****
那么指定 GuavaCacheManager 为 @Primary,此时的CacheConfig类代码****
package com.ding.data.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.cache.CacheManager;
import org.springframework.cache.guava.GuavaCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
@Configuration
public class CacheConfig implements ApplicationRunner {
@Resource
private List<CacheManager> cacheManagers;
public void run(ApplicationArguments args) throws Exception {
System.out.println("CacheManager大小为=========" + cacheManagers.size());
System.out.println("=================================================");
for(CacheManager c:cacheManagers){
System.out.println(c.getCacheNames());
}
}
@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(
RedisTemplate<Object, Object> redisTemplate) {
redisTemplate.setKeySerializer(new StringRedisSerializer());
RedisCacheManager redisCacheManager = new RedisCacheManager(
redisTemplate);
redisCacheManager.setCacheNames(Arrays.asList("redisDemo"));
redisCacheManager.setUsePrefix(true);
return redisCacheManager;
}
@Bean(name = "guavaCacheManager")
@Primary
public GuavaCacheManager getGuavaCacheManager() {
GuavaCacheManager guavaCacheManager = new GuavaCacheManager();
guavaCacheManager.setCacheBuilder(CacheBuilder.newBuilder()
.expireAfterWrite(3600, TimeUnit.SECONDS).maximumSize(1000));
ArrayList<String> guavaCacheNames = Lists.newArrayList();
guavaCacheNames.add("guavaDemo");
guavaCacheManager.setCacheNames(guavaCacheNames);
return guavaCacheManager;
}
// @Bean(name = "cacheManager")
// @Primary
// public CompositeCacheManager cacheManager(
// RedisCacheManager redisCacheManager,
// GuavaCacheManager guavaCacheManager) {
// CompositeCacheManager cacheManager = new CompositeCacheManager(
// redisCacheManager, guavaCacheManager);
// return cacheManager;
// }
}