SpringCache是一个基于注解来更新缓存的组件,对于大多数的缓存操作都适用,本质是基于AOP实现,也不用再重复千轮子,直接使用便是,并且支持SpringEL表达式,对于使用教程网上还是很多的。
很多时候为了兼容性以及方便,会把对象转换成JSON格式存入缓存(Redis)中,这就需要对Cache进行拦截,在加入缓存及获取缓存时做一个JSON格式转换。
通过@EnableCaching 打开Spring Cache,查看@EnableCaching 定义可以看到此切面配置类默认是 ProxyCachingConfiguration,它有一个叫CacheInterceptor 的默认实现。所有缓存操作都需要经过它,只需自定义此类即可。如下所示例:
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public CacheInterceptor cacheInterceptor(CacheOperationSource cacheOperationSource) {
CacheInterceptor interceptor = new CacheInterceptor() {
private static final long serialVersionUID = 1L;
@Override
protected void doPut(Cache cache, Object key, Object result) {
String jsonResult = JSON.toJSONString(result);
super.doPut(cache, key, jsonResult);
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Method method = invocation.getMethod();
MyCacheOperationInvoker aopAllianceInvoker = new MyCacheOperationInvoker(invocation);
try {
Object result = execute(aopAllianceInvoker, invocation.getThis(), method,
invocation.getArguments());
if (result != null && result instanceof String && !aopAllianceInvoker.isDoInvoke()) {
Type resultType = method.getGenericReturnType();
return JSON.parseObject((String) result, resultType);
}
return result;
} catch (CacheOperationInvoker.ThrowableWrapper th) {
throw th.getOriginal();
}
}
};
interceptor.setCacheOperationSources(cacheOperationSource);
return interceptor;
}
class MyCacheOperationInvoker implements CacheOperationInvoker {
private MethodInvocation invocation;
private boolean doInvoke = false;
public MyCacheOperationInvoker(MethodInvocation invocation) {
this.invocation = invocation;
}
@Override
public Object invoke() {
try {
doInvoke = true;
return invocation.proceed();
} catch (Throwable ex) {
throw new ThrowableWrapper(ex);
}
}
public boolean isDoInvoke() {
return doInvoke;
}
}
上面方案对于所有缓存都有效,如果缓存使用的是Redis,还可以通过自定义 RedisTemplate ,替换RedisSerializer序列化方式。把自定的RedisTemplate注入到CacheManager中即可。
版权声明:本文为synsdeng原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。