This article mainly introduces the precautions for java spring-cache key configuration. The editor thinks it is quite good. I will share it with you here for the reference of friends who need it.
In order to improve the concurrency performance of the project, consider introducing local memory Cache to cache three types of function processing results: external data source access, Restful API calls, and reusable complex calculations. Currently, the @Cacheable annotation method of spring Cache is used, and the specific implementation of the cache is Guava Cache.
The specific cache configuration will not be introduced here, but the key configuration will be explained:
1. Basic form
@Cacheable(value="cacheName", key"#id") public ResultDTO method(int id);
2. Combination form
@Cacheable(value="cacheName", key"T(String).valueOf(#name).concat('-').concat(#password)) public ResultDTO method(int name, String password);
3. Object form
@Cacheable(value="cacheName", key"#user.id) public ResultDTO method(User user);
4. Custom key generator
@Cacheable(value="gomeo2oCache", keyGenerator = "keyGenerator") public ResultDTO method(User user);
Note: Spring’s default SimpleKeyGenerator does not combine function names The
in the key is as follows:
@Component public class CacheTestImpl implements CacheTest { @Cacheable("databaseCache") public Long test1() { return 1L; } @Cacheable("databaseCache") public Long test2() { return 2L; } @Cacheable("databaseCache") public Long test3() { return 3L; } @Cacheable("databaseCache") public String test4() { return "4"; } }
We expect the output:
1 2 3 4
Actual output:
1 1 1 ClassCastException: java.lang.Long cannot be cast to java.lang.String
In addition, arrays of atomic types will not take effect if used directly as keys
In order to solve the above 2 For a problem, I customized a KeyGenerator as follows:
class CacheKeyGenerator implements KeyGenerator { // custom cache key public static final int NO_PARAM_KEY = 0; public static final int NULL_PARAM_KEY = 53; @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()); } 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(); } }
Using this method can solve: problems such as multiple parameters, atomic type arrays, method name identification, etc.
Summarize
The above is the detailed content of Notes on Cache key configuration in Java Spring. For more information, please follow other related articles on the PHP Chinese website!