这篇文章主要讲解了Spring cache如何整合redis,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
创新互联是一家专注于成都网站设计、网站建设与策划设计,邛崃网站建设哪家好?创新互联做网站,专注于网站建设十年,网设计领域的专业建站公司;建站业务涵盖:邛崃等地区。邛崃做网站价格咨询:18982081108
Spring-Cache是Spring3.1引入的基于注解的缓存技术,本质上它并不是一个具体的缓存实现,而是一个对缓存使用的抽象,通过Spring AOP技术,在原有的代码上添加少量的注解来实现将这个方法转成缓存方法的效果。
本来想来个分析源码,奈何水平有限,先从实战搞起。
先引入依赖:
org.springframework.boot spring-boot-starter-data-redis 2.1.6.RELEASE redis.clients jedis 2.9.3
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.defaultCacheConfig() //设置缓存超时时间 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.isSynchronized()) { 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 synchronizedT get(Object key, Callable valueLoader) { 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已经写入,过期时间也存在
现在我们删除缓存
看完上述内容,是不是对Spring cache如何整合redis有进一步的了解,如果还想学习更多内容,欢迎关注创新互联行业资讯频道。