springboot增加注解緩存@Cacheable的實(shí)現(xiàn)
springboot增加注解緩存@Cacheable
業(yè)務(wù)層使用
@Cacheable(value = "dictionary#1800", key = "#root.targetClass.simpleName +':'+ #root.methodName +':'+ #code")
public Object findByCode(String code) {
//業(yè)務(wù)
}
配置
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 {
/**
* 過(guò)期時(shí)間分隔符
*/
private static final String TTLSEPARATOR = "#";
private final ConcurrentMap<String, Cache> cacheMap = new ConcurrentHashMap(16);
/**
* 過(guò)期時(shí)間, 單位為 秒
*/
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) {
//設(shè)置序列化Key的實(shí)例化對(duì)象
redisTemplate.setKeySerializer(new StringRedisSerializer());
//設(shè)置序列化Value的實(shí)例化對(duì)象
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
指定緩存組件的名字,通過(guò)下面代碼可以看出可以將返回結(jié)果放在哪個(gè)緩存中,可以通過(guò)數(shù)組的方式指定多個(gè)緩存
/**
* 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ù)的時(shí)候使用的key,它是用來(lái)指定對(duì)應(yīng)的緩存,模擬使用方法參數(shù)值作為key的值。也可以使用SpEL表達(dá)式的值來(lái)指定
/**
* 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 | 當(dāng)前被調(diào)用的目標(biāo)對(duì)象 | #root.target |
| targetClass | root object | 當(dāng)前被調(diào)用的目標(biāo)對(duì)象類 | #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 |
可以通過(guò)這個(gè)參數(shù)提示列表看看到這個(gè)key所支持的root object對(duì)象有哪些,通過(guò)這樣的方式可以指定對(duì)應(yīng)的key值。

keyGenerator
這個(gè)是表示指定的key的生成器,當(dāng)然在之前分享中我們說(shuō)過(guò)一個(gè)簡(jiǎn)單的key的生成策略。這里我們還可以通過(guò)自定的方式來(lái)實(shí)現(xiàn)這個(gè)key的生成策略。
keyGenerator
這個(gè)是表示指定的key的生成器,當(dāng)然在之前分享中我們說(shuō)過(guò)一個(gè)簡(jiǎn)單的key的生成策略。這里我們還可以通過(guò)自定的方式來(lái)實(shí)現(xiàn)這個(gè)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()+"]";
}
};
}
}
在使用的時(shí)候可以通過(guò)一下的方式進(jìn)行配置
@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
指定復(fù)合條件的情況下才緩存。也可以通過(guò)SpEL表達(dá)式進(jìn)行設(shè)置。這個(gè)配置規(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(除非)
當(dāng)這個(gè)條件為true的時(shí)候,方法的返回值就不會(huì)被緩存。
/**
* 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;
注意
在使用這個(gè)屬性的時(shí)候,當(dāng)這個(gè)屬性為true的時(shí)候,unless屬性是不能使用的。
{@link #unless()} is not supported
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Collections工具類_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
Collections工具類提供了大量針對(duì)Collection/Map的操作。這篇文章主要介紹了Collections工具類_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理,需要的朋友可以參考下2017-04-04
Java實(shí)現(xiàn)局域網(wǎng)聊天小程序
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)局域網(wǎng)聊天小程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
java對(duì)象拷貝常見(jiàn)面試題及應(yīng)答匯總
在本篇文章里小編給大家整理的是關(guān)于java對(duì)象拷貝常見(jiàn)面試題的相關(guān)內(nèi)容,需要的朋友們可以學(xué)習(xí)下。2020-02-02
Fluent Mybatis零xml配置實(shí)現(xiàn)復(fù)雜嵌套查詢
本文主要介紹了Fluent Mybatis零xml配置實(shí)現(xiàn)復(fù)雜嵌套查詢,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
SpringBoot導(dǎo)入Druid運(yùn)行失敗問(wèn)題
這篇文章主要介紹了SpringBoot導(dǎo)入Druid運(yùn)行失敗,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09

