spring-data-redis底层源码解析

spring-data-redis底层源码解析

1. 对SpringDataRedis介绍

SpringDataRedis是Spring大家族中的一个成员,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行了高度封装,RedisTemplate提供了redis各种操作、异常处理及序列化,支持发布订阅,并对spring 3.1 cache进行了实现,spring redis同时支持了Jedis,Jredis,rjc 客户端操作。

2.spring redis 源码设计逻辑

  1. Redis连接管理:封装了Jedis,Jredis,Rjc等不同redis 客户端连接
  2. Redis操作封装:value,list,set,sortset,hash划分为不同操作
  3. Redis序列化:能够以插件的形式配置想要的序列化实现
  4. Redis操作模板化: redis操作过程分为:获取连接,业务操作,释放连接;模板方法使得业务代码只需要关心业务操作
  5. Redis事务模块:在同一个回话中,采用同一个redis连接完成

3. spring redis连接管理模块分析

spring redis封装了不同redis 客户端,对于底层redis客户端的抽象分装,使其能够支持不同的客户端;连接管理模块的具体类大概有以下:

类名 职责
RedisConnection 提供了Redis通信的核心构建块,因为它处理与Redis后端通信。它还自动将底层连接库异常转换为Spring一致的DAO异常层次结构,这样就可以在不更改任何代码的情况下切换连接器,因为操作语义保持不变。(简单理解下,就是用来连接Redis的)
RedisConnectionFactory 是构建RedisConnection的工厂类
RedisCommands 继承了Redis各种数据类型操作的整合接口
JedisConnection 实现RedisConnection接口,将操作委托给Jedis
JedisConnectionFactory 实现RedisConnectionFactory接口,创建JedisConnection

spring-data-redis针对jedis提供了如下功能:

  1. 连接池自动管理,提供了一个高度封装的“RedisTemplate”类

通过RedisTemplate处理对象
RedisTemplate是Spring为方便操作Redis各种命令而封装出来的工具类,是spring data redis 中的核心操作类,提供了丰富的,通用的接口,用于针对某种类型或某些键
spring-data-redis底层源码解析_第1张图片
2. 针对jedis客户端中大量api进行了归类封装,将同一类型操作封装为operation接口
spring-data-redis底层源码解析_第2张图片
在这里插入图片描述在这里插入图片描述

在这里插入图片描述
spring-data-redis底层源码解析_第3张图片
在这里插入图片描述

关键绑定操作
BoundGeoOperations Redis键绑定地理空间操作
BoundHashOperations Redis哈希键绑定操作
BoundKeyOperations Redis键绑定操作
BoundListOperations Redis列表键绑定操作
BoundSetOperations Redis设置键绑定操作
BoundValueOperations Redis字符串(或值)键绑定操作
BoundZSetOperations Redis zset(或排序集)键绑定操作

RedisOperations
RedisTemplate实现了RedisOperations
在这里插入图片描述
RedisOperations(封装了Redis的各种数据操作)
其中每一种操作类型有都进行了接口封装.下面就看一下五种数据类型的操作接口
ValueOperations

spring-data-redis底层源码解析_第4张图片
ListOperations对应List
spring-data-redis底层源码解析_第5张图片
SetOperations对应Set
spring-data-redis底层源码解析_第6张图片
ZSetOperations对应 sortedSet
spring-data-redis底层源码解析_第7张图片
HashOperations对应于Hash
spring-data-redis底层源码解析_第8张图片
两个模板类提供的数据访问方法.(五种类型的数据操作方法).这些方法调用Redis的命令的方式提供了实现.当然还有基于注解的操作Redis.

 opsForValue():操作只有简单属性的数据.String.

 opsForList():操作含有list的数据.

 opsForSet():操作含有set的数据

 opsForZSet():操作含有ZSet(有序的set)的数据.

 opsForHash():操作含有hash的数据.
 
序列化器 Serializer

在Spring Data中,用户(自定义)类型和原始数据之间的转换(反之亦然)在org.springframework.data.redis.serializer包中的Redis中进行处理
我们数据存储到Redis的时候,我们的键值Key和Value都是通过Spring提供的Serializer序列化到db中的

spring-data-redis底层源码解析_第9张图片
spring data 提供的序列化工具
spring-data-redis底层源码解析_第10张图片
提供的有相关的序列化器
spring-data-redis底层源码解析_第11张图片

4. demo项目配置

(1) 构建 Maven 工程 SpringDataRedisDemo
spring-data-redis底层源码解析_第12张图片
(2) 添加相关启动器Lombok、Spring Data Redis、spring-data-common

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 使用spring-data-common -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-commons</artifactId>
    <version>2.2.0.RELEASE</version>
</dependency>
<!-- 添加jedis依赖 -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.0.1</version>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

(3) 在resources下新建redis-config. properties文件并加入redis相关配置

# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host-name=49.232.162.73
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=100
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=10000
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=5
# 连接超时时间(毫秒)
spring.redis.timeout=1000000
## 最大连接数
spring.redis.pool.max-total=200

(4) 在config包下创建redis配置类RedisConfig.java

package com.demoredis.demoredis.config;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

/**
 * @author 笑笑小太阳
 * @date 2019/12/26 11:33
 */
@Configuration
@PropertySource(value = { "classpath:redis-config.properties" })
public class RedisConfig  {
    /**
     * 连接池配置信息
     * @return
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis.pool")
    public JedisPoolConfig jedisPoolConfig() {
        JedisPoolConfig config = new JedisPoolConfig();
        return config;
    }

    /**
     * 2.创建RedisConnectionFactory:配置redis 链接信息
     */
    @Bean
    @ConfigurationProperties(prefix = "spring.redis")
    public RedisConnectionFactory redisConnectionFactory(JedisPoolConfig config) {

        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        JedisClientConfiguration.JedisPoolingClientConfigurationBuilder jpcf = (JedisClientConfiguration.JedisPoolingClientConfigurationBuilder) JedisClientConfiguration
                .builder();
        // 修改我们的连接池配置
        jpcf.poolConfig(config);
        // 通过构造器来构造jedis客户端配置
        JedisClientConfiguration jedisClientConfiguration = jpcf.build();
        return new JedisConnectionFactory(redisStandaloneConfiguration);
    }

    /**
     *  RedisTemplate(或StringRedisTemplate)虽然已经自动配置,但是不灵活(第一没有序列化,第二泛型为不是我们想要的类型)
     *  所以自己实现RedisTemplate或StringRedisTemplate)
     */
    @Bean(name = "redisTemplate")
    public RedisTemplate<String, Object> redisTemplate(JedisConnectionFactory factory) {
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(factory);
        setRedisTemplate(redisTemplate);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }
    public void setRedisTemplate(RedisTemplate redisTemplate) {
        //        JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
        GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // 设置值(value)的序列化采用FastJsonRedisSerializer。
        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
        //        redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
        // 设置键(key)的序列化采用StringRedisSerializer。
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.afterPropertiesSet();
    }
}


(5) 创建实体类 必须要实现序列化接口

@Data
public class Emp implements java.io.Serializable {
    /**
     * 版本号
     */
    private static final long serialVersionUID = -5129628746900026803L;
    /**
     * 编号
     */
    private Integer empno;
    /**
     * 姓名
     */
    private String empname;
    /**
     * 性别
     */
    private String sex;
    /**
     * 年龄
     */
    private Integer age;

    /**
     * 邮箱
     */
    private String email;
    /**
     * 部门编号
     */
    private Integer deptid;
    private String password;


}

(6) 测试类测试代码

 @Resource
RedisTemplate<String, Object> redisTemplate;

@Test
void testString() {
    redisTemplate.opsForValue().set("admin", "root");

}

@Test
void testStringGet() {
    String str = (String) redisTemplate.opsForValue().get("admin");

    System.out.println(str + "====");
}

@Test
void testObject() {

    User user = new User(1, "zhandsgan", 20);
   redisTemplate.opsForValue().set("user1",user);
}


@Test
void testGetObject() {


     User  user=(User) redisTemplate.opsForValue().get("user1");
    System.out.println(user);
}


@Test
public   void   testHaseSet(){
    redisTemplate.opsForHash().put("aa","code","admin");
}

}

如果有问题,可以私聊我

你可能感兴趣的:(spring-data-redis底层源码解析)