Atitit spring cache key的生成 与ken生成规范
1. Good key name meth.params 1
1.1. Use epl 的mode but only clss method ,and single param 1
1.4. CacheKeyGeneratorSpring 5
1. Good key name meth.params
Good key gene is class.method as package...
Param as sub package..
1.1. Use epl 的mode but only clss method ,and single param
1.2. 4、自定义key生成器
[java] view plain copy
1. @Cacheable(value="gomeo2oCache", keyGenerator = "keyGenerator")
2. public ResultDTO method(User user);
注意:Spring默认的SimpleKeyGenerator是不会将函数名组合进key中的
使用@EnableCaching启用Cache注解支持;
2、实现CachingConfigurer,然后注入需要的cacheManager和keyGenerator;从spring4开始默认的keyGenerator是SimpleKeyGenerator;
即如果只有一个参数,就使用参数作为key,否则使用SimpleKey作为key。
我们也可以自定义自己的key生成器,然后通过xml风格的<cache:annotation-driven key-generator=""/>或注解风格的CachingConfigurer中指定keyGenerator。
<!-- ati cache cfg-->
<bean id="CacheKeyGeneratorSpringAti" class="com.cnhis.cloudhealth.clinical.util.cache.CacheKeyGeneratorSpring">
</bean>
<context:annotation-config/>
<cache:annotation-driven key-generator="CacheKeyGeneratorSpringAti"/>
3. 使用 direct use or ,define the @Cacheable(value="gomeo2oCache", keyGenerator = "keyGenerator")
If cfg in spring xml..then default use ..
spring
1.3. Spring xml cfg
<!-- ati cache cfg-->
<bean id="CacheKeyGeneratorSpringAti" class="com.cnhis.cloudhealth.clinical.util.cache.CacheKeyGeneratorSpring">
</bean>
<context:annotation-config/>
<cache:annotation-driven key-generator="CacheKeyGeneratorSpringAti"/>
<!--
<bean id="cacheManager"
class="org.springframework.cache.concurrent.ConcurrentMapCacheManager" />
//C:\0wkspc\clis413\clinical\src\main\java\com\cnhis\cloudhealth\clinical\util\cache\MyConcurrentMapCacheManager.java
-->
<!-- (long expireTime sec, long maximumSize)
<bean id="cacheManager"
class="com.cnhis.cloudhealth.clinical.util.cache.MyConcurrentMapCacheManager">
<constructor-arg index="0" value="70" />
<constructor-arg index="1" value="500000" />
</bean>
<context:property-placeholder location="classpath:META-INF/prop/redis.properties"/>
-->
<context:property-placeholder location="classpath:META-INF/prop/redis.properties,classpath*:/META-INF/prop/newid.properties,classpath*:/META-INF/prop/jdbc.properties" />
<!--缓存管理器-->
<bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
<property name="caches">
<set>
<!--自定义的redis缓存操作实现-->
<bean class="com.cnhis.cloudhealth.clinical.util.cache.SpringCacheWzRedis">
<property name="name" value="Cachename1"/>
<property name="redisTemplate" ref="redisTemplate"/>
</bean>
</set>
</property>
</bean>
<!--redis连接池配置-->
<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
<property name="maxIdle" value="${redis.maxIdle}"/>
<!--
<property name="maxTotal" value="${redis.maxTotal}"/>
-->
<property name="testOnBorrow" value="${redis.testOnBorrow}"/>
</bean>
<!--redis连接工厂配置-->
<bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
<property name="password" value="${redis.pass}"/>
<property name="poolConfig" ref="poolConfig"/>
<property name="usePool" value="true"/>
<property name="database" value="2"/>
</bean>
<!--redis操作模板-->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="connectionFactory"/>
</bean>
<!-- end ati cache -->
<!-- end ati cache -->
1.4. CacheKeyGeneratorSpring
package com.cnhis.cloudhealth.clinical.util.cache;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.util.ClassUtils;
import com.alibaba.fastjson.JSON;
import com.google.common.hash.Hashing;
// com.cnhis.cloudhealth.clinical.util.cache.CacheKeyGeneratorSpring
public class CacheKeyGeneratorSpring implements KeyGenerator {
// custom cache key
public static final int NO_PARAM_KEY = 0;
public static final int NULL_PARAM_KEY = 53;
private static Logger log = LoggerFactory.getLogger(CacheKeyGeneratorSpring.class);
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder key = new StringBuilder();
key.append(target.getClass().getSimpleName()).append(".").append(method.getName()).append(":");
if (params.length == 0) {
return key.append(NO_PARAM_KEY).toString();
}
for (Object param : params) {
if (param == null) {
log.warn("input null param for Spring cache, use default key={}", NULL_PARAM_KEY);
key.append(NULL_PARAM_KEY);
} else if (ClassUtils.isPrimitiveArray(param.getClass())) {
int length = Array.getLength(param);
for (int i = 0; i < length; i++) {
key.append(Array.get(param, i));
key.append(',');
}
} else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {
key.append(param);
} else {
log.warn("Using an object as a cache key may lead to unexpected results. " +
"Either use @Cacheable(key=..) or implement CacheKey. Method is " + target.getClass() + "#" + method.getName());
// key.append(param.hashCode());
if( param instanceof Map )
{
key.append( JSON.toJSONString(param) );
}
}
key.append('-');
}
String finalKey = key.toString();
long cacheKeyHash = Hashing.murmur3_128().hashString(finalKey, Charset.defaultCharset()).asLong();
log.debug("using cache key={} hashCode={}", finalKey, cacheKeyHash);
return key.toString();
}
}