1.配置类
@Configuration
@EnableCaching
public class RedisConfigurer extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
String className = target.getClass().getName().replace("com.duia.home.service.impl.","").replace("ServiceImpl","");
sb.append(className+".");
sb.append(method.getName()+".");
for (Object obj : params) {
if (obj instanceof Date){
sb.append( DateUtils.format((Date) obj,"yyyy-MM-dd"));
}else {
sb.append (obj.toString());
}
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate<?, ?> redisTemplate) {
// 创建缓存管理器
ArrayList<String> cacheNames = new ArrayList<>();
cacheNames.add("home");
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate,cacheNames);
cacheManager.setDefaultExpiration(3600*24);
cacheManager.setUsePrefix(true);
cacheManager.setCachePrefix(new DefaultRedisCachePrefix(":"));
return cacheManager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
@EnableCaching
public class RedisConfigurer extends CachingConfigurerSupport {
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
String className = target.getClass().getName().replace("com.duia.home.service.impl.","").replace("ServiceImpl","");
sb.append(className+".");
sb.append(method.getName()+".");
for (Object obj : params) {
if (obj instanceof Date){
sb.append( DateUtils.format((Date) obj,"yyyy-MM-dd"));
}else {
sb.append (obj.toString());
}
}
return sb.toString();
}
};
}
@Bean
public CacheManager cacheManager(@SuppressWarnings("rawtypes") RedisTemplate<?, ?> redisTemplate) {
// 创建缓存管理器
ArrayList<String> cacheNames = new ArrayList<>();
cacheNames.add("home");
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate,cacheNames);
cacheManager.setDefaultExpiration(3600*24);
cacheManager.setUsePrefix(true);
cacheManager.setCachePrefix(new DefaultRedisCachePrefix(":"));
return cacheManager;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
StringRedisTemplate template = new StringRedisTemplate(factory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
2.使用实例
@Cacheable(value = "usercache",keyGenerator = "keyGenerator")
public List<CourseLiveNewDto> findTodayOpenLivesBySku(Integer sku, Date now, Integer flag) {
}
3.结构图
3.源码分析
一.服务启动,当properties加载完后,将缓存管理器里(如redis库)的数据放到内存中
1.先执行3中的public void afterPropertiesSet() {this.initializeCaches();}
public void initializeCaches() {
Collection caches = this.loadCaches();
synchronized(this.cacheMap) {
....
while(var4.hasNext()) {
...
this.cacheMap.put(name, this.decorateCache(cache));
cacheNames.add(name);
}
}
}
3.先执行5的loadCaches
protected Collection<? extends Cache> loadCaches() {
Set caches = new Set((Collection)(this.loadRemote?this.loadAndInit():new ArrayList()));//从redis中获取key
...
caches.add(this.createCache(cacheName));//从redis中获取k-v值
}
}
return caches;
}
|
protected RedisCache createCache(String cacheName) {
long expiration = this.computeExpiration(cacheName);
return new RedisCache(cacheName, this.usePrefix?this.cachePrefix.prefix(cacheName):null, this.redisOperations, expiration, this.cacheNullValues);
}
|
二.第一次请求service
1.执行5的getCache
public Cache getCache(String name) {
Cache cache = (Cache)this.cacheMap.get(name);//从内存中取name的值
if(cache != null) {
return cache;
} else {
。...
return cache;
}
}
}
|
2.放开执行方法返回时启动CacheAspectSupport切面类方法execute将结果保存到redis和内存中
private Object execute(...) {
....
returnValue = this.invokeOperation(invoker);
cacheValue = this.unwrapReturnValue(returnValue);
....
cachePutRequest.apply(cacheValue);
return returnValue;
}
}
|
public void apply(Object result) {
if(this.context.canPutToCache(result)) {
Iterator var2 = this.context.getCaches().iterator();
while(var2.hasNext()) {
Cache cache = (Cache)var2.next();
CacheAspectSupport.this.doPut(cache, this.key, result);
}
}
}
|
3.构造RedisCache
public void put(Object key, Object value) {
this.put((new RedisCacheElement(this.getRedisCacheKey(key), this.toStoreValue(value))).expireAfter(this.cacheMetadata.getDefaultExpiration()));
}
|
private RedisCacheKey getRedisCacheKey(Object key) {
return (new RedisCacheKey(key)).usePrefix(this.cacheMetadata.getKeyPrefix()).withKeySerializer(this.redisOperations.getKeySerializer());
}
|
public byte[] prefix(String cacheName) {
return this.serializer.serialize(this.delimiter != null?cacheName.concat(this.delimiter):cacheName.concat(":"));
}
|
4.从缓存中读取
public Cache getCache(String name) {
Cache cache = (Cache)this.cacheMap.get(name);//从内存中取name的值
if(cache != null) {
return cache;
} else {
。...
return cache;
}
}
}