轻量级前端框架助力开发者提升项目效率与性能
595
2023-06-08
Spring cache整合redis代码实例
Spring-Cache是Spring3.1引入的基于注解的缓存技术,本质上它并不是一个具体的缓存实现,而是一个对缓存使用的抽象,通过Spring AOP技术,在原有的代码上添加少量的注解来实现将这个方法转成缓存方法的效果。
本来想来个分析源码,奈何水平有限,先从实战搞起。
先引入依赖:
redis配置:
server:
port: 8000
spring:
redis:
host: 23.95.x.x
port: 6379
timeout: 20s
database: 0
jedis:
pool:
max-active: 5
max-idle: 3
max-wait: 5s
password: testtest
配置类:
package me.yanand.config;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2jsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
@EnableCaching
public class RedisConfig{
private Duration timeOut = Duration.ofMinutes(30);
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defQFaSAcllIaultCacheConfig()
//设置缓存超时时间 30分钟
.entryTtl(timeOut)
//设置key序列化方式
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
//设置value序列化方式
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
.disableCachingNullValues();
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).transactionAware().build();
}
}
主要看@EnableCaching注解,这个注解引入了@Import(CachingConfigurationSelector.class),通过CachingConfigurationSelector把代理创建类、CacheInterceptor、CacheOperationSource、BeanFactoryCacheOperationSourceAdvisor注入到容器,spring通过CacheInterceptor-拦截相关带有@Cacheable、@CacheEvict、@CachePut注解的方法并执行相关缓存操作。
CacheInterceptor相关源码:
@Nullable
private Object execute(final CacheOperationInvoker invoker, Method method, CacheOperationContexts contexts) {
if (contexts.QFaSAcllIisSynchronized()) {
CacheOperationContext context = contexts.get(CacheableOperation.class).iterator().next();
//满足条件执行
if (isConditionPassing(context, CacheOperationExpressionEvaluator.NO_RESULT)) {
Object key = generateKey(context, CacheOperationExpressionEvaluator.NO_RESULT);
Cache cache = context.getCaches().iterator().next();
try {
//这里主要看RedisCache的get方法
return wrapCacheValue(method, cache.get(key, () -> unwrapReturnValue(invokeOperation(invoker))));
}
catch (Cache.ValueRetrievalException ex) {
// The invoker wraps any Throwable in a ThrowableWrapper instance so we
// can just make sure that one bubbles up the stack.
throw (CacheOperationInvoker.ThrowableWrapper) ex.getCause();
}
}
else {
//不满足直接执行相关方法
return invokeOperation(invoker);
}
}
...省略
}
RedisCache相关代码:
public synchronized
ValueWrapper result = get(key);
//缓存中有值则返回
if (result != null) {
return (T) result.get();
}
//缓存中不存在则执行相关方法
T value = valueFromLoader(key, valueLoader);
put(key, value);
return value;
}
注解使用:
package me.yanand.dao;
import me.yanand.pojo.User;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class UserDao {
@Cacheable(cacheNames = "users",key = "#root.targetClass+#name", unless = "#result eq null")
public User getUser(String name){
return new User("张三",30);
}
@CacheEvict(cacheNames = "users", key = "#root.targetClass+#name")
public void delUser(String name){
}
}
测试:
通过postman触发相关方法,现在我们连上redis查看缓存写入情况
这里我们看到key已经写入,过期时间也存在
现在我们删除缓存
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~