欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-03 10:49:11
目录springboot增加注解缓存@cacheable业务层使用配置@cacheable注解的属性使用cachenames和valuekeykeygeneratorkeygeneratorcondi...

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

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

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

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

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

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

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