Spring Cache自定义缓存格式

       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版权协议,转载请附上原文出处链接和本声明。