Spring cache整合redis代码实例

 更新时间:2020年04月28日 11:50:17   作者:Terry  
这篇文章主要介绍了Spring cache整合redis代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

Spring-Cache是Spring3.1引入的基于注解的缓存技术,本质上它并不是一个具体的缓存实现,而是一个对缓存使用的抽象,通过Spring AOP技术,在原有的代码上添加少量的注解来实现将这个方法转成缓存方法的效果。

本来想来个分析源码,奈何水平有限,先从实战搞起。

先引入依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
  <version>2.1.6.RELEASE</version>
</dependency>
<dependency>
  <groupId>redis.clients</groupId>
  <artifactId>jedis</artifactId>
  <version>2.9.3</version>
</dependency>

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 synchronized <T> T get(Object key, Callable<T> 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已经写入,过期时间也存在

现在我们删除缓存

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java状态设计模式实现对象状态转换的优雅方式

    Java状态设计模式实现对象状态转换的优雅方式

    Java状态设计模式通过将对象的行为和状态分离,使对象能够根据不同的状态进行不同的行为操作。它通过将状态抽象成一个独立的类来实现对状态的封装,从而简化了复杂的条件判断和状态转换
    2023-04-04
  • java通过客户端访问服务器webservice的方法

    java通过客户端访问服务器webservice的方法

    这篇文章主要介绍了java通过客户端访问服务器webservice的方法,涉及java创建与调用webservice的相关技巧,需要的朋友可以参考下
    2016-08-08
  • Mybatis-Plus和Mybatis的区别详解

    Mybatis-Plus和Mybatis的区别详解

    这篇文章主要介绍了Mybatis-Plus和Mybatis的区别,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-08-08
  • Dubbo3和Spring Boot整合过程源码解析

    Dubbo3和Spring Boot整合过程源码解析

    Dubbo首先是提供了一个单独的模块来和Spring Boot做整合,利用 Spring Boot自动装配的功能,配置了一堆自动装配的组件,本文介绍Dubbo3和Spring Boot整合过程,需要的朋友一起看看吧
    2023-08-08
  • Java设计模式之抽象工厂模式简析

    Java设计模式之抽象工厂模式简析

    这篇文章主要介绍了Java设计模式之抽象工厂模式简析, 抽象工厂模式是工厂方法模式的升级版本,他用来创建一组相关或者相互依赖的对象,他与工厂方法模式的区别就在于,工厂方法模式针对的是一个产品等级结构,需要的朋友可以参考下
    2023-12-12
  • MyBatis批量插入的五种方式

    MyBatis批量插入的五种方式

    这篇文章主要介绍了MyBatis批量插入的五种方式,每种方式结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-11-11
  • 剑指Offer之Java算法习题精讲链表专项训练

    剑指Offer之Java算法习题精讲链表专项训练

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03
  • Java内存模型知识详解

    Java内存模型知识详解

    这篇文章主要介绍了Java内存模型知识详解,文中通过对内存访问时的交互关系图解介绍的十分详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • java 中线程等待与通知的实现

    java 中线程等待与通知的实现

    这篇文章主要介绍了java 中线程等待与通知的实现的相关资料,希望通过本文能帮助到大家,让大家掌握这样的功能,需要的朋友可以参考下
    2017-09-09
  • 详解Java中的final关键字的使用

    详解Java中的final关键字的使用

    这篇文章主要介绍了详解Java中的final关键字的使用,是Java入门学习中的基础知识,需要的朋友可以参考下
    2015-07-07

最新评论