Spring中的aware接口详情
227
2022-09-07
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 clanrtAAeTZblss MyRedisCacheManager extends RedisCacheManager {
/**
* 过期时间分隔符
*/
private static final String TTLSEPARATOR = "#";
private final ConcurrentMap
/**
* 过期时间, 单位为 秒
*/
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) {
nrtAAeTZbl 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.
*
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 LangunrtAAeTZblage (SpEL) expression for computing the key dynamically.
*
Default is {@code ""}, meaning all method parameters are considered as a key,
* unless a custom {@link #keyGenerator} has been configured.
*
The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
*
*
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.
*
* ({@code #root.targetClass}) are also available.
*
* 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.
*
*/
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;
@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.
*
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.
*
Default is {@code ""}, meaning the method result is always cached.
*
The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
*
*
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.
*
* ({@code #root.targetClass}) are also available.
*
* 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.
*
*/
String condition() default "";
unless(除非)
当这个条件为true的时候,方法的返回值就不会被缓存。
/**
* Spring Expression Language (SpEL) expression used to veto method caching.
*
Unlike {@link #condition}, this expression is evaluated after the method
* has been called and can therefore refer to the {@code result}.
*
Default is {@code ""}, meaning that caching is never vetoed.
*
The SpEL expression evaluates against a dedicated context that provides the
* following meta-data:
*
*
* supported wrappers such as {@code Optional}, {@code #result} refers to the actual
* object, not the wrapper
*
* references to the {@link java.lang.reflect.Method method}, target object, and
* affected cache(s) respectively.
*
* ({@code #root.targetClass}) are also available.
*
* 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.
*
* @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:
*
*
*
*
*
* 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
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~