深入理解Spring-data-redie源码

spring全家桶新成员,分析阅读Spring Data Redis源码

前言

公司项目交付完成,最近抽空阅读了SpringData-Redis的源码,

简介

Spring Data Redis是较大的Spring数据家族的一部分,它提供了从Spring应用程序轻松配置和访问redis的功能。它提供了与存储交互的低级和高级抽象,使用户从基础设施的关注中解放出来。
功能特色
作为多个ReIIS驱动程序的低层抽象的连接包
在Spring Boot中,官方提供了spring-boot-autoconfigure包和starter包用来帮助我们简化配置,比如之前要建一个Spring mvc项目,需要我们配置web.xml,dispatcherservlet-servlet.xml,applicationContext.xml等等。而在Spring Boot中只需要在pom中引入

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

然后在application.properties中配置ip,密码等必要参数

spring.redis.host=106.15.108.50
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=123456

源码解析

在application.properties中ctrl+左击redis的相关配置项,会打开spring-boot-autoconfigure\2.0.2.RELEASE\spring-boot-autoconfigure-2.0.2.RELEASE.jar中的RedisProperties。
旧版本依赖、我们可以看到旧版本的maven中默认使用了jedis连接池。

在这里插入图片描述
新版本依赖
在这里插入图片描述
通过idea的maven插件我们可以看到在最新版本的SpringBootspring-Data-Redis的起步依赖中去除了原先的jedis连接池,引入了lettuce连接池。
原先的jedis已经被lettuce替代。在高并发场景下jedis已经无法满足需求、jedis客户端并不是线程安全的,在开中线程安全一直是开发中需要注意的问题。springData已经不再把jedis作为默认连接池,如果在项目中使用jedis连接池需要手动开启jedis配置。

旧版本包结构
在这里插入图片描述
新版本源包结构
在这里插入图片描述
Jedis 是一个很老牌的 Redis 的 Java 开发包,使用很稳定,作者维护很勤勉,社区上能搜到的文章也非常非常多。算是使用范围最广的 Redis 开发包。但是 Jedis 比较推出时间比较早,整个设计思路比较传统,例如不支持异步操作,接口设计比较繁琐老套(相比其他开发包而已),使用连接池占用很多的物理连接资源。当然,这个是可以理解的,比较一个比较早期的开发包,相对其做大的结构调整是很难的,而且用户也不一定会接受。

关于jedis跟lettuce的区别:

  • LettuceJedis 的定位都是Redisclient,所以他们当然可以直接连接redis server。
  • Jedis在实现上是直接连接的redis server,如果在多线程环境下是非线程安全的,这个时候只有使用连接池,为每个Jedis实例增加物理连接
  • Lettuce的连接是基于Netty的,连接实例(StatefulRedisConnection)可以在多个线程间并发访问,应为StatefulRedisConnection是线程安全的,所以一个连接实例(StatefulRedisConnection)就可以满足多线程环境下的并发访问,当然这个也是可伸缩的设计,一个连接实例不够的情况也可以按需增加连接实例。
  • Jedis:使用阻塞的I/O,且其方法调用都是同步的,程序流需要等到sockets处理完I/O才能执行,不支持异步。Jedis客户端实例不是线程安全的,所以需要通过连接池来使用Jedis。
  • Lettuce:基于Netty框架的事件驱动的通信层,其方法调用是异步的。Lettuce的API是线程安全的,所以可以操作单个Lettuce连接来完成各种操作

SpringBoot对Redis的支持.

我们可以在idea通过双击Shift建进行全局文件搜索
在这里插入图片描述
搜索到你要找的类点击就可以查看该类
RedisConnectionFactory
在这里插入图片描述
RedisCommands接口多继承各种操作命令接口
在这里插入图片描述

public interface RedisCommands<K, V> extends BaseRedisCommands<K, V>, 
RedisClusterCommands<K, V>, RedisGeoCommands<K, V>, RedisHashCommands<K, V>, 
RedisHLLCommands<K, V>, RedisKeyCommands<K, V>, RedisListCommands<K, V>, 
RedisScriptingCommands<K, V>, RedisServerCommands<K, V>, RedisSetCommands<K, V>,
 RedisSortedSetCommands<K, V>, RedisStreamCommands<K, V>, RedisStringCommands<K, 
 V>, RedisTransactionalCommands<K, V> {
    String auth(String var1);

    String select(int var1);

    String swapdb(int var1, int var2);

    StatefulRedisConnection<K, V> getStatefulConnection();
}

RedisKeyCommands接口 定了常用的key操作封装为key命令接口
就是将Redis的各种命令封装成了Java的实现方法了.
在这里插入图片描述

RedisConnection接口定义Redis的连接抽象方法
在这里插入图片描述

JedisConnectionFactory接口
在这里插入图片描述
已经过时的方法JedisConnectionFactory(JedisShardInfo shardInfo)
在这里插入图片描述
JedisConnectionFacotory从Spring Data Redis 2.0开始已经不推荐直接显示设置连接的信息了,一方面为了使配置信息与建立连接工厂解耦,另一方面抽象出Standalone,Sentinel和RedisCluster三种模式的环境配置类和一个统一的jedis客户端连接配置类(用于配置连接池和SSL连接),使得我们可以更加灵活方便根据实际业务场景需要来配置连接信息。

如果定义reidsServer的配置,springData-redis默认配置
在这里插入图片描述
如果使用时未传入JedisClientConfiguration 对象
默认实例化 当前类的this.clientConfiguration ;
在这里插入图片描述

	//无参构造
public JedisConnectionFactory() {
        this((JedisClientConfiguration)(new JedisConnectionFactory.MutableJedisClientConfiguration()));
    }
	//重载有参构造
    private JedisConnectionFactory(JedisClientConfiguration clientConfig) {
        this.providedShardInfo = false;
        this.convertPipelineAndTxResults = true;
        this.standaloneConfig = new RedisStandaloneConfiguration("localhost", 6379);
        Assert.notNull(clientConfig, "JedisClientConfiguration must not be null!");
        //将传入的对象给 类变量clientConfiguration 赋值
        this.clientConfiguration = clientConfig;
    }

AbstractRedisConnection类定义抽象的连接方法,实现RedisConnection
在这里插入图片描述

RedisProperties
org.springframework.boot.autoconfigure.data.redis.RedisProperties 会根据配置自动加载为一个bean
在这里插入图片描述
@ConfigurationProperties(prefix = “spring.redis”)
设置绑定属性的前缀。前缀 + 前缀现在回到配置文件看是不是感觉很熟悉,这不就是我们在配置文件中配置的redis连接参数吗!如果我们没有配置端口这种属性,那么这里也会提供部分默认配置。
当然,只是这些是没办法让Spring Boot在启动时扫描到该类的,所以需要下一个类org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.class。
然后我们还能找到

private final Jedis jedis = new Jedis();
private final Lettuce lettuce = new Lettuce();

RedisAutoConfiguration


@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
    public RedisAutoConfiguration() {
    }

    @Bean
    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }

    @Bean
    @ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        StringRedisTemplate template = new StringRedisTemplate();
        template.setConnectionFactory(redisConnectionFactory);
        return template;
    }
}

RedisAutoConfiguration
包位置org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration

在这里插入图片描述

  1. @Configuration常见的配置注解,内部含有一个以上的@Bean,让Spring能扫描到内部的@Bean,当然在Spring
    Boot中,默认只会扫描到启动类所在包或其下级包的类,所以还会通过其他的设置来让这个类被扫描到,这个后面会详细说明。

@Configuration用于定义配置类,可替换xml配置文件,被注解的类内部包含有一个或多个被@Bean注解的方法,这些方法将会被AnnotationConfigApplicationContext或AnnotationConfigWebApplicationContext类进行扫描,并用于构建bean定义,初始化Spring容器。

  1. @EnableConfigurationProperties(RedisProperties.class)让RedisProperties
    类被扫描到的关键。这时,如果RedisAutoConfiguration被扫描到,则同时也会去扫描RedisProperties类。
  2. @Import({ LettuceConnectionConfiguration.class,
    JedisConnectionConfiguration.class })通过@Import注解方式生成类实例并注入Spring容器。

发现其会引入spring-data-redis,因此只有当我们在pom中引入spring-boot-starter-data-redis时,RedisAutoConfiguration才会真正的开启扫描。这也体现了Spring Boot的即插即用和方便快捷的自动配置。
然后下面还有一个io.lettuce,而之前在RedisAutoConfiguration中我们知道redisTemplate方法最终会把一个LettuceConnectionFactory实例注入Spring容器,而在这里实际上就已经大致表明了RedisAutoConfiguration会使用Lettuce客户端了。

总结

当要使用Spring Boot提供的redis客户端功能时,注入RedisTemplate的流程大致如下。
1.pom中引入spring-boot-starter-data-redis,并配置application.properties。
2.pom会根据spring-boot-starter-data-redis来引入spring-data-redis
3.spring-data-redis中包含RedisOperations类。
4.启动Spring Boot,在refreshContext(context);中会初始化beanFactory,读取配置信息,初始化Spring容器,注入bean。因为**@EnableAutoConfiguration开启的关系,会读取配置中EnableAutoConfiguration相关的类,并实例化注入Spring 容器。
5.根据配置文件扫描到
RedisAutoConfiguration**。当RedisOperations存在时RedisAutoConfiguration才会被扫描。
6.通过@EnableConfigurationProperties(RedisProperties.class)和@ConfigurationProperties(prefix = “spring.redis”),把application.properties中的对应属性进行绑定,并注入RedisProperties配置类。
7.RedisAutoConfiguration中的@Import会引入LettuceConnectionConfiguration和JedisConnectionConfiguration
8.LettuceConnectionConfiguration和JedisConnectionConfiguration被扫描,扫描到内部的**@Bean,使用上一步中注入的RedisProperties** bean作为参数来实例化LettuceConnectionFactory和JedisConnectionFactory,并以RedisConnectionFactory类注入Spring容器。
8.扫描并注入RedisAutoConfiguration类内的@Bean,其中会使用RedisConnectionFactory bean作参数实例化RedisTemplate
9.将RedisTemplate实例注入。
10.然后就能通过引用RedisTemplate来操作redis了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值