赞
踩
本文分享自华为云社区《【Spring Boot 源码学习】RedisAutoConfiguration 详解》,作者: Huazie。
带大家分析 Spring Boot 内置的有关 Redis 的自动配置类【RedisAutoConfiguration】。
Spring Data Redis 是 Spring Data 家族的一部分,它提供了从 Spring 应用程序中轻松配置和访问 Redis 的功能。
我们来看看官方介绍的特性:
在 Spring Data Redis 中,我们可以直接使用 RedisTemplate 及其相关的类来操作 Redis。虽然 RedisConnection 提供了接受和返回二进制值(字节数组)的低级方法,但 RedisTemplate 负责序列化和连接管理,使用户可以无需处理这些细节。
RedisTemplate 还提供了操作视图(按照 Redis 命令参考进行分组),这些视图提供了丰富、通用的接口,用于针对特定类型或特定键进行操作(通过 KeyBound 接口实现),如下表所示:
下面我们来看看相关的 Spring 配置:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
-
- <bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:use-pool="true"/>
- <!-- redis 模板定义 -->
- <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate" p:connection-factory-ref="jedisConnFactory"/>
-
- </beans>
一旦配置完成,Redis 模板就是线程安全的,并且可以在多个实例之间重用。
RedisTemplate 使用基于 Java 的序列化器进行大部分操作。也就意味着通过模板写入或读取的任何对象都是通过 Java 进行序列化和反序列化的。
我们也可以更改模板上的序列化机制,可以添加如下配置:
- <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
- <property name="connectionFactory" ref="redisConnectionFactory"/>
- <property name="keySerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
- </property>
- <property name="valueSerializer">
- <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
- </property>
- <property name="hashKeySerializer">
- <bean class="org.springframework.data.redis.serializer.StringRedisSerializer"/>
- </property>
- <property name="hashValueSerializer">
- <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"/>
- </property>
- </bean>
而 Redis 模块提供了几个序列化器的实现,有关这些实现大家可以查看 org.springframework.data.redis.serializer 包。
还可以将任何序列化程序设置为 null,并通过设置 enableDefaultSerializer 属性为 false 来使用RedisTemplate 与原始字节数组一起使用。
注意: 模板要求所有键都不为空。但是,只要底层序列化程序接受值,值就可以为空。
下面我们可以注入 RedisTemplate,并调用 RedisTemplate 的方法进行存储、查询、删除等操作。
- @Autowired
- private RedisTemplate<String, Object> redisTemplate;
- // 存储数据
- redisTemplate.opsForValue().set("key", "value");
- // 查询数据
- Object value = redisTemplate.opsForValue().get("key");
- // 删除数据
- redisTemplate.delete("key");
对于需要特定模板视图的情况,声明视图作为依赖项并注入模板。容器会自动执行转换,消除opsFor[X] 调用,如下所示的示例:
- public class Example {
- // inject the template as ListOperations
- @Resource(name="redisTemplate")
- private ListOperations<String, String> listOps;
-
- public void addLink(String userId, URL url) {
- listOps.leftPush(userId, url.toExternalForm());
- }
- }
当然 Spring Data Redis 肯定不止上述这些,有需要深入了解的读者们,请看如下:
参考: Spring Data Redis 官方文档
那么 Spring Data Redis 的 RedisTemplate 的自动配置在 Spring Boot 是如何实现的呢?
Spring Boot 是通过内置的 RedisAutoConfiguration 配置类来完成这一功能。下面我们具体分析一下:
注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。
从之前的《【Spring Boot 源码学习】自动装配流程源码解析(上)》中,我们知道 Spring Boot 内部针对自动配置类,会读取如下两个配置文件:
实际上 在 Spring Boot 2.7.9 版本中, Spring Boot 自己内部的 META-INF/spring.factories 中有关自动配置的注册类的配置信息已经被去除掉了,不过其他外围的 jar 中可能有自己的 META-INF/spring.factories 文件,它里面也有关于自动配置注册类的配置信息;
而 Spring Boot 内置的 RedisAutoConfiguration 配置类,则是配置在上述的第二个配置文件 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中。
上述自动配置加载完之后,就来到了 《【Spring Boot 源码学习】自动装配流程源码解析(下)》 介绍的 过滤自动配置组件 逻辑。
这部分数据对应的配置内容在 META-INF/spring-autoconfigure-metadata.properties 文件中:
- org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration=
- org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration.ConditionalOnClass=org.springframework.data.redis.core.RedisOperations
显然这里涉及到了 ConditionalOnClass 注解,我们翻看 RedisAutoConfiguration 配置类的源码,如下:
- @AutoConfiguration
- @ConditionalOnClass(RedisOperations.class)
- @EnableConfigurationProperties(RedisProperties.class)
- @Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
- public class RedisAutoConfiguration {
-
- @Bean
- @ConditionalOnMissingBean(name = "redisTemplate")
- @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
- public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
- // 。。。
- }
-
- @Bean
- @ConditionalOnMissingBean
- @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
- public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
- // 。。。
- }
-
- }
2.2.1 涉及注解
我们先来看看上述 RedisAutoConfiguration 配置类涉及到的注解,如下:
2.2.2 RedisProperties
其中 RedisProperties 类的属性值对应着 application.yml 或 application.properties 中的配置,通过注解@ConfigurationProperties(prefix = "spring.redis") 实现的属性注入。
有关属性注入的内容后续笔者会另外介绍,我们先来看看RedisProperties 类相关的部分源码 和 对应的配置参数:
- @ConfigurationProperties(prefix = "spring.redis")
- public class RedisProperties {
-
- // 。。。
-
- // Redis 服务器主机地址.
- private String host = "localhost";
-
- // 。。。
-
- // Redis 服务器的端口
- private int port = 6379;
-
- private Sentinel sentinel;
-
- private Cluster cluster;
-
- private final Jedis jedis = new Jedis();
-
- private final Lettuce lettuce = new Lettuce();
-
- // Redis 连接池配置
- public static class Pool {
- // 。。。
- }
- // Redis 集群配置
- public static class Cluster {
- // 。。。
- }
- // Redis 哨兵配置
- public static class Sentinel {
- // 。。。
- }
- // Jedis 客户端配置
- public static class Jedis {
-
- // Jedis 连接池配置
- private final Pool pool = new Pool();
- }
- // Lettuce 客户端配置
- public static class Lettuce {
- // Lettuce 连接池配置
- private final Pool pool = new Pool();
-
- private final Cluster cluster = new Cluster();
- }
- }
然后在 application.properties 中,我们就可以添加类似如下的配置:
- # Redis 单机配置
- spring.redis.host=127.0.0.1
- spring.redis.port=31113
-
- # Redis 集群配置
- # nodes属性是Redis集群节点的地址和端口,用逗号分隔。
- spring.redis.cluster.nodes=192.168.1.1:7000,192.168.1.2:7001,192.168.1.3:7002
- # max-redirects属性是最大重定向次数,用于处理节点故障的情况。
- spring.redis.cluster.max-redirects=3
-
- # mymaster是哨兵模式下的主节点名称。
- spring.redis.sentinel.master=mymaster
- # nodes是哨兵模式下的从节点地址和端口。
- spring.redis.sentinel.nodes=192.168.1.1:26379,192.168.1.2:26379,192.168.1.3:26379
-
- # ...其他配置省略
先来看看 redisTemplate 方法的源码【Spring Boot 2.7.9】:
- @Bean
- @ConditionalOnMissingBean(name = "redisTemplate")
- @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
- public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
- RedisTemplate<Object, Object> template = new RedisTemplate<>();
- template.setConnectionFactory(redisConnectionFactory);
- return template;
- }
上述逻辑表示只有在当前上下文中不存在名为 "redisTemplate" 的 Bean 时,才会创建一个名为 redisTemplate 的 RedisTemplate Bean,并将其与一个可用的 Redis 连接工厂关联起来。
我们再来看看 stringRedisTemplate 方法的源码【Spring Boot 2.7.9】:
- @Bean
- @ConditionalOnMissingBean
- @ConditionalOnSingleCandidate(RedisConnectionFactory.class)
- public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
- return new StringRedisTemplate(redisConnectionFactory);
- }
上述逻辑也好理解,它表示只有在当前上下文中不存在名为 "stringRedisTemplate" 的 Bean 时,才会创建一个名为stringRedisTemplate的 StringRedisTemplate Bean,并将其与一个可用的 Redis 连接工厂关联起来。
StringRedisTemplate 是 RedisTemplate 的子类,专门用于处理字符串类型的数据。
StringRedisTemplate 使用的是 StringRedisSerializer,它在存入数据时会将数据先序列化成字节数组。
默认情况下,StringRedisTemplate 采用的序列化策略有两种:
本篇我们深入分析了 RedisAutoConfiguration 配置类的相关内容,进一步加深了对自动配置装配流程的了解。
HDC 2024,6月21日-23日,东莞松山湖,期待与您相见!
更多详情请关注官网:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。