springboot增加注解缓存@Cacheable的实现

目录springboot增加注解缓存@Cacheable业务层使用配置@Cacheable注解的属性使用cacheNames和valuekeykeyGeneratorkeyGeneratorconditionunless(除非)sync

springboot增加注解缓存@Cacheable

业务层使用

@Cacheable(value = "dictionary#1800", key = "#root.targetClass.simpleName +':'+ #root.methodName +':'+ #code")    public Object findByCode(String code) {        //业务    }

配置

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@EnableCachingpublic 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

指定缓存组件的名字,通过下面代码可以看出可以将返回结果放在哪个缓存中,可以通过数组的方式指定多个缓存

 /**  * 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表达式的值来指定

 /**  * 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的生成策略。

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;@Configurationpublic 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表达式进行设置。这个配置规则和上面表格中的配置规则是相同的。

 /**  * 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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

充满了恐惧的声音,一种不确定的归宿的流动。

springboot增加注解缓存@Cacheable的实现

相关文章:

你感兴趣的文章:

标签云: