springboot增加注解缓存@Cacheable的实现
这篇文章主要介绍了springboot增加注解缓存@Cacheable的实现,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
目录
springboot增加注解缓存@Cacheable
业务层使用
配置
@Cacheable注解的属性使用
cacheNames和value
key
keyGenerator
keyGenerator
condition
unless(除非)
sync
springboot增加注解缓存@Cacheable
业务层使用
1 2 3 4 | @Cacheable (value = "dictionary#1800" , key = "#root.targetClass.simpleName +':'+ #root.methodName +':'+ #code" ) public Object findByCode(String code) { //业务 } |
配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | import org.springframework.cache.Cache; import org.springframework.data.redis.cache.RedisCache; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.core.RedisOperations; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; public class MyRedisCacheManager extends RedisCacheManager { /** * 过期时间分隔符 */ private static final String TTLSEPARATOR = "#" ; private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap( 16 ); /** * 过期时间, 单位为 秒 */ private long defaultExpiration = 0 ; public MyRedisCacheManager(RedisOperations redisOperations) { super (redisOperations); } @Override public Cache getCache(String name) { long expiredTime = defaultExpiration; if (name.contains(TTLSEPARATOR)) { String[] split = name.split(TTLSEPARATOR); String cacheName = split[ 0 ]; try { expiredTime = Double.valueOf(split[ 1 ]).longValue(); } catch (Exception e) { e.printStackTrace(); } Cache cache = this .cacheMap.get(name); if (cache != null ) { return cache; } else { synchronized ( this .cacheMap) { cache = this .cacheMap.get(name); if (cache == null ) { cache = new RedisCache(cacheName, null , super .getRedisOperations(), expiredTime); if (cache != null ) { cache = this .decorateCache(cache); this .cacheMap.put(name, cache); } } return cache; } } } return super .getCache(name); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheConfig; import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; @CacheConfig @Configuration @EnableCaching public class RedisConfig extends CachingConfigurerSupport { @Bean public CacheManager cacheManager(RedisTemplate redisTemplate) { //设置序列化Key的实例化对象 redisTemplate.setKeySerializer( new StringRedisSerializer()); //设置序列化Value的实例化对象 ObjectMapper mapper = new ObjectMapper(); mapper.findAndRegisterModules(); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(mapper); redisTemplate.setValueSerializer(serializer); MyRedisCacheManager mrc = new MyRedisCacheManager(redisTemplate); return mrc; } } |
@Cacheable注解的属性使用
cacheNames和value
指定缓存组件的名字,通过下面代码可以看出可以将返回结果放在哪个缓存中,可以通过数组的方式指定多个缓存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * Alias for {@link #cacheNames}. */ @AliasFor ( "cacheNames" ) String[] value() default {}; /** * Names of the caches in which method invocation results are stored. * <p>Names may be used to determine the target cache (or caches), matching * the qualifier value or bean name of a specific bean definition. * @since 4.2 * @see #value * @see CacheConfig#cacheNames */ @AliasFor ( "value" ) String[] cacheNames() default {}; |
key
缓存数据的时候使用的key,它是用来指定对应的缓存,模拟使用方法参数值作为key的值。也可以使用SpEL表达式的值来指定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * Spring Expression Language (SpEL) expression for computing the key dynamically. * <p>Default is {@code ""}, meaning all method parameters are considered as a key, * unless a custom {@link #keyGenerator} has been configured. * <p>The SpEL expression evaluates against a dedicated context that provides the * following meta-data: * <ul> * <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for * references to the {@link java.lang.reflect.Method method}, target object, and * affected cache(s) respectively.</li> * <li>Shortcuts for the method name ({@code #root.methodName}) and target class * ({@code #root.targetClass}) are also available. * <li>Method arguments can be accessed by index. For instance the second argument * can be accessed via {@code #root.args[1]}, {@code #p1} or {@code #a1}. Arguments * can also be accessed by name if that information is available.</li> * </ul> */ String key() default "" ; |
名称 | 位置 | 描述 | 示例 |
---|---|---|---|
methodName | root object | 被调用的方法名称 | #root.methodName |
Method | root object | 被调用的方法 | #root.method.name |
Target | root object | 当前被调用的目标对象 | #root.target |
targetClass | root object | 当前被调用的目标对象类 | #root.targetClass |
args | root object | 被调用方法的参数列表#root.args[0] | |
caches | root object | 调用的缓存列表 | #root.caches[0].name |
argument name | evaluation context | 方法的参数名称可以直接使用#参数名 | #p0,#a0等等 |
result | evaluation context | 执行方法后的返回值 | #result |
可以通过这个参数提示列表看看到这个key所支持的root object对象有哪些,通过这样的方式可以指定对应的key值。
keyGenerator
这个是表示指定的key的生成器,当然在之前分享中我们说过一个简单的key的生成策略。这里我们还可以通过自定的方式来实现这个key的生成策略。
keyGenerator
这个是表示指定的key的生成器,当然在之前分享中我们说过一个简单的key的生成策略。这里我们还可以通过自定的方式来实现这个key的生成策略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.lang.reflect.Method; import java.util.Arrays; @Configuration public class MyCacheConfig { @Bean ( "myKeyGenerator" ) public KeyGenerator keyGenerator(){ return new KeyGenerator() { @Override public Object generate(Object target, Method method, Object... params) { return method.getName()+ "[" + Arrays.asList(params).toString()+ "]" ; } }; } } |
在使用的时候可以通过一下的方式进行配置
1 | @Cacheable (cacheNames = { "emp" },keyGenerator = "myKeyGenerator" ) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | cacheManager指定缓存管理器 /** * The bean name of the custom {@link org.springframework.cache.CacheManager} to use to * create a default {@link org.springframework.cache.interceptor.CacheResolver} if none * is set already. * <p>Mutually exclusive with the {@link #cacheResolver} attribute. * @see org.springframework.cache.interceptor.SimpleCacheResolver * @see CacheConfig#cacheManager */ String cacheManager() default "" ; /** * The bean name of the custom {@link org.springframework.cache.interceptor.CacheResolver} * to use. * @see CacheConfig#cacheResolver */ String cacheResolver() default "" ; |
condition
指定复合条件的情况下才缓存。也可以通过SpEL表达式进行设置。这个配置规则和上面表格中的配置规则是相同的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /** * Spring Expression Language (SpEL) expression used for making the method * caching conditional. * <p>Default is {@code ""}, meaning the method result is always cached. * <p>The SpEL expression evaluates against a dedicated context that provides the * following meta-data: * <ul> * <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for * references to the {@link java.lang.reflect.Method method}, target object, and * affected cache(s) respectively.</li> * <li>Shortcuts for the method name ({@code #root.methodName}) and target class * ({@code #root.targetClass}) are also available. * <li>Method arguments can be accessed by index. For instance the second argument * can be accessed via {@code #root.args[1]}, {@code #p1} or {@code #a1}. Arguments * can also be accessed by name if that information is available.</li> * </ul> */ String condition() default "" ; |
unless(除非)
当这个条件为true的时候,方法的返回值就不会被缓存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | /** * Spring Expression Language (SpEL) expression used to veto method caching. * <p>Unlike {@link #condition}, this expression is evaluated after the method * has been called and can therefore refer to the {@code result}. * <p>Default is {@code ""}, meaning that caching is never vetoed. * <p>The SpEL expression evaluates against a dedicated context that provides the * following meta-data: * <ul> * <li>{@code #result} for a reference to the result of the method invocation. For * supported wrappers such as {@code Optional}, {@code #result} refers to the actual * object, not the wrapper</li> * <li>{@code #root.method}, {@code #root.target}, and {@code #root.caches} for * references to the {@link java.lang.reflect.Method method}, target object, and * affected cache(s) respectively.</li> * <li>Shortcuts for the method name ({@code #root.methodName}) and target class * ({@code #root.targetClass}) are also available. * <li>Method arguments can be accessed by index. For instance the second argument * can be accessed via {@code #root.args[1]}, {@code #p1} or {@code #a1}. Arguments * can also be accessed by name if that information is available.</li> * </ul> * @since 3.2 */ String unless() default "" ; |
sync
是否异步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /** * Synchronize the invocation of the underlying method if several threads are * attempting to load a value for the same key. The synchronization leads to * a couple of limitations: * <ol> * <li>{@link #unless()} is not supported</li> * <li>Only one cache may be specified</li> * <li>No other cache-related operation can be combined</li> * </ol> * This is effectively a hint and the actual cache provider that you are * using may not support it in a synchronized fashion. Check your provider * documentation for more details on the actual semantics. * @since 4.3 * @see org.springframework.cache.Cache#get(Object, Callable) */ boolean sync() default false ; |
注意
在使用这个属性的时候,当这个属性为true的时候,unless属性是不能使用的。
1 | { @link #unless()} is not supported |
以上为个人经验,希望能给大家一个参考
原文链接:https://yasugongshang.blog.csdn.net/article/details/81773325