springboot增加注解緩存@Cacheable的實現(xiàn)
springboot增加注解緩存@Cacheable
業(yè)務層使用
@Cacheable(value = "dictionary#1800", key = "#root.targetClass.simpleName +':'+ #root.methodName +':'+ #code") public Object findByCode(String code) { //業(yè)務 }
配置
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); } }
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
指定緩存組件的名字,通過下面代碼可以看出可以將返回結(jié)果放在哪個緩存中,可以通過數(shù)組的方式指定多個緩存
/** * 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
緩存數(shù)據(jù)的時候使用的key,它是用來指定對應的緩存,模擬使用方法參數(shù)值作為key的值。也可以使用SpEL表達式的值來指定
/** * 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 | 被調(diào)用的方法名稱 | #root.methodName |
Method | root object | 被調(diào)用的方法 | #root.method.name |
Target | root object | 當前被調(diào)用的目標對象 | #root.target |
targetClass | root object | 當前被調(diào)用的目標對象類 | #root.targetClass |
args | root object | 被調(diào)用方法的參數(shù)列表#root.args[0] | |
caches | root object | 調(diào)用的緩存列表 | #root.caches[0].name |
argument name | evaluation context | 方法的參數(shù)名稱可以直接使用#參數(shù)名 | #p0,#a0等等 |
result | evaluation context | 執(zhí)行方法后的返回值 | #result |
可以通過這個參數(shù)提示列表看看到這個key所支持的root object對象有哪些,通過這樣的方式可以指定對應的key值。
keyGenerator
這個是表示指定的key的生成器,當然在之前分享中我們說過一個簡單的key的生成策略。這里我們還可以通過自定的方式來實現(xiàn)這個key的生成策略。
keyGenerator
這個是表示指定的key的生成器,當然在之前分享中我們說過一個簡單的key的生成策略。這里我們還可以通過自定的方式來實現(xiàn)這個key的生成策略。
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()+"]"; } }; } }
在使用的時候可以通過一下的方式進行配置
@Cacheable(cacheNames = {"emp"},keyGenerator = "myKeyGenerator")
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表達式進行設置。這個配置規(guī)則和上面表格中的配置規(guī)則是相同的。
/** * 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的時候,方法的返回值就不會被緩存。
/** * 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
是否異步
/** * 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屬性是不能使用的。
{@link #unless()} is not supported
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Spring MVC集成springfox-swagger2構(gòu)建restful API的方法詳解
這篇文章主要給大家介紹了關于Spring MVC集成springfox-swagger2構(gòu)建restful API的相關資料,文中介紹介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。2017-06-06springboot 集成cas5.3 實現(xiàn)sso單點登錄詳細流程
SSO的定義是在多個應用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統(tǒng)。單點登錄是目前比較流行的企業(yè)業(yè)務整合的解決方案之一,本文給大家介紹springboot 集成cas5.3 實現(xiàn)sso單點登錄功能,感興趣的朋友一起看看吧2021-10-10Spring Boot與Kotlin 整合全文搜索引擎Elasticsearch的示例代碼
本篇文章主要介紹了Spring Boot與Kotlin 整合全文搜索引擎Elasticsearch的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-01-01基于Java多線程notify與notifyall的區(qū)別分析
本篇文章對Java中多線程notify與notifyall的區(qū)別進行了詳細的分析介紹。需要的朋友參考下2013-05-05Dapr在Java中的服務調(diào)用實戰(zhàn)過程詳解
這篇文章主要為大家介紹了Dapr在Java中的服務調(diào)用實戰(zhàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-06-06Spring?boot?整合RabbitMQ實現(xiàn)通過RabbitMQ進行項目的連接
RabbitMQ是一個開源的AMQP實現(xiàn),服務器端用Erlang語言編寫,支持多種客戶端,這篇文章主要介紹了Spring?boot?整合RabbitMQ實現(xiàn)通過RabbitMQ進行項目的連接,需要的朋友可以參考下2022-10-10解決spring-boot2.0.6中webflux無法獲得請求IP的問題
這幾天在用 spring-boot 2 的 webflux 重構(gòu)一個工程,寫到了一個需要獲得客戶端請求 IP 的地方,在寫的過程中遇到很多問題,下面小編通過一段代碼給大家介紹解決spring-boot2.0.6中webflux無法獲得請求IP的問題,感興趣的朋友跟隨小編一起看看吧2018-10-10