SpringBoot集成Redis(全流程详解)

前言

通过在SpringBoot中集成Redis,详细梳理集成过程。包括SpringBoot启动过程中,容器的刷新、自动配置的流程、各类注解的处理。

类比在纯Spring中集成Redis,体验SpringBoot自动配置给开发带来了哪些便利。

一、测试样例

1.1配置文件

application.yml

spring:redis:host: *.*.*.*port: 6379password: 123456database: 0timeout: 1000lettuce:pool:max-active: 8max-idle: 8min-idle: 0

1.2依赖项

pom.xml

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

SpringBoot中默认自带了Redis客户端lettuce

image-20241114103352729

1.3单元测试类

package com.lazy.snail;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;@SpringBootTest
class ApplicationTests {@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Testvoid contextLoads() {stringRedisTemplate.opsForValue().set("name", "lazysnail");stringRedisTemplate.opsForValue().set("email", "lazy_snail@aliyun.com");}}
  • 测试结果:

image-20241114105038125

二、自动配置机制版本差异

Spring Boot自2.7版本开始逐步弃用spring.factories文件,并在3.0版本中将其彻底移除。

2.1SpringBoot2.7版本前

image-20241114110648852

在/META-INF/目录下,包含了一系列的自动配置类,这些类可以在满足特定条件时被Spring Boot自动加载和使用。

2.2SpringBoot2.7.x版本

image-20241114110819604

/META-INF/spring目录下新增了org.springframework.boot.autoconfigure.AutoConfiguration.imports,将原本spring.factories中的自动配置类移过来了。

2.3SpringBoot2.6.x及2.7.x获取候选自动配置类差异

2.7.x版本新增了@AutoConfiguration标记类的处理

image-20241114110001934

2.4SpringBoot3.x获取候选自动配置类

3.x后移除了spring.factories的处理

image-20241114111638663

2.5redis自动配置差异

2.7.x版本后引入了@AutoConfiguration注解。

@AutoConfiguration注解表明该类提供的配置可以被Spring Boot自动应用。

image-20241114145909183

[!NOTE]

Spring Boot 3.x移除spring.factories中自动配置类的处理机制主要是为了:

增强模块化和清晰性,减少隐式依赖。

适应Spring 6和Java 17的现代化要求。

提供更加显式和可控的配置机制,使得开发者能够更好地理解和调试自动配置的过程。

更好地支持条件化配置和@ConfigurationProperties等现代配置方式。

Spring 6和Java 17还没仔细的研究过,后续再分享这块内容

三、redis集成流程

3.1SpringBoot启动过程刷新容器

3.1.1调用BeanFactoryPostProcessor

  • 实例化ConfigurationClassPostProcessor

image-20241114151752941

  • 调用BeanDefinitionRegistryPostProcessor(ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor)

image-20241114151859664

  • 处理配置类bean定义信息
    1. 找到Application(启动SpringBoot的主类)(@SpringBootApplication注解中有@Configuration注解)
    2. 解析处理Application类上的注解
    3. 处理@Import注解(@SpringBootApplication注解中的@EnableAutoConfiguration注解含有@Import(AutoConfigurationImportSelector.class))

image-20241114152440691

  • 获取自动配置类入口

image-20241114153020458

  • 获取候选自动配置类

image-20241114153136769

  • 2.7.x版本从spring.factories和org.springframework.boot.autoconfigure.AutoConfiguration.imports中获取配置类

image-20241114153250081

  • redis自动配置类的全限定名被获取到

image-20241114153448705

  • 经过去重、排除、过滤器,筛选出可用配置类

image-20241114153735039

  • 过滤器主要通过配置类上@ConditionalOnClass等条件进行匹配,不符合条件的配置类将被筛除

image-20241114153927132

  • RedisAutoConfiguration作为普通配置类进行解析

image-20241114154451820

  • 处理RedisAutoConfiguration的@Import

image-20241114155139212

  • 引入LettuceConnectionConfiguration配置

​ 由于没有引入Jedis客户端依赖,JedisConnectionConfiguration配置类会被跳过

image-20241114155646289

所有的配置类都解析完成后 (俄罗斯套娃结束),把配置类上所有的bean配置(@Bean、@Import(xxx.Registrar.class)等)加载为bean定义信息。

3.1.2finishBeanFactoryInitialization实例化所有剩余的单例

实例化后,容器中已经存在stringRedisTemplate和redisTemplate实例,可以直接注入使用

image-20241114161534979

四、Redis自动配置类详解

4.1SpringBoot2.7.x版本RedisAutoConfiguration源码

package org.springframework.boot.autoconfigure.data.redis;import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;@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) {RedisTemplate<Object, Object> template = new RedisTemplate<>();template.setConnectionFactory(redisConnectionFactory);return template;}@Bean@ConditionalOnMissingBean@ConditionalOnSingleCandidate(RedisConnectionFactory.class)public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {return new StringRedisTemplate(redisConnectionFactory);}}

4.2注解说明

1.@AutoConfiguration

  • 作用:@AutoConfiguration是Spring Boot 2.7.0引入的注解,用于标记一个类为自动配置类。自动配置类是Spring Boot启动时根据条件自动注入到 Spring 容器中的配置类。
  • 工作原理:这个注解通过条件注解(如@ConditionalOnClass、@ConditionalOnMissingBean)确定是否应该应用某些配置。它的功能类似于@EnableAutoConfiguration和@Configuration的组合。

2. @ConditionalOnClass(RedisOperations.class)

  • 作用:这是一个条件注解,当类路径中存在RedisOperations时,才会加载这个配置类。
  • 具体含义:@ConditionalOnClass(RedisOperations.class) 表明只有在类路径下找到RedisOperations类时,RedisAutoConfiguration 才会被加载。RedisOperations是Spring Data Redis中的接口,代表Redis操作的基本API,因此,只有在Redis相关依赖存在时Redis自动配置才会生效。
  • 本案例在pom中引入了spring-boot-starter-data-redis依赖项,所以类路径下存在RedisOperations。

3. @EnableConfigurationProperties(RedisProperties.class)

  • 作用:这个注解可以让RedisProperties类的属性能够被注入到Spring容器中。RedisProperties类用来读取application.properties或 application.yml中关于Redis相关的配置。
  • 具体含义:RedisProperties类包含Redis配置的相关属性(如 Redis 服务器地址、端口、密码等),@EnableConfigurationProperties注解确保这些配置能够被自动加载并绑定到相应的属性类中。

4. @Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})

  • 作用:@Import注解用于引入其他配置类。这里会把LettuceConnectionConfiguration和JedisConnectionConfiguration两个配置类导入进来。
  • 具体含义:Spring Data Redis提供了两个主要的客户端(spring-boot-starter-data-redis自带了Lettuce的实现,如果需要使用Jedis还要引入redis.clients):Lettuce和Jedis,这两个类负责Redis连接的配置。通过@Import,Redis自动配置类可以根据需要选择使用其中之一来配置Redis连接。

5. @Bean

  • 作用:@Bean注解用于将一个方法标记为一个 Bean,方法返回值将作为Spring容器中的一个Bean。Spring会管理这个Bean的生命周期,并根据需要注入到其他地方。
  • 具体含义:@Bean注解的作用是将redisTemplate和stringRedisTemplate方法返回的对象注册为Spring容器中的Bean。这样,Spring 容器就会自动注入这两个模板类的实例到需要使用Redis的地方。
  • 本案例直接在单元测试类中注入stringRedisTemplate,既可以对redis进行一些简单的操作。

6. @ConditionalOnMissingBean(name = “redisTemplate”)

  • 作用:这个注解表示当Spring容器中没有名为"redisTemplate"的Bean时,才会执行该方法并创建RedisTemplate的Bean。
  • 具体含义:如果容器中已经存在一个名为 “redisTemplate” 的 Bean,redisTemplate方法不会被调用,也不会再次创建一个新的 RedisTemplate实例。防止覆盖已经存在的Redis配置。

7. @ConditionalOnSingleCandidate(RedisConnectionFactory.class)

  • 作用:这个注解表示只有当Spring容器中存在且仅有一个RedisConnectionFactory类型的Bean时,才会执行该方法。
  • 具体含义:RedisConnectionFactory是Redis连接的核心接口,@ConditionalOnSingleCandidate确保在容器中只有一个符合条件的连接工厂时,才会进行Redis模板的创建。避免多个Redis连接工厂的冲突。

8. @ConditionalOnMissingBean

  • 作用:这个注解表示当Spring容器中没有指定类型的Bean时,才会执行该方法并创建对应的Bean。
  • 具体含义:如果容器中没有定义过StringRedisTemplate类型的Bean,就会调用 stringRedisTemplate方法创建并注册这个Bean。如果容器中已有这个类型的Bean,这个方法不会被执行。

五、集成完善(初级)

5.1封装一个Redis工具类的redis服务

package com.lazy.snail;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import java.util.List;
import java.util.concurrent.TimeUnit;/*** @ClassName RedisService* @Description TODO* @Author lazysnail* @Date 2024/11/14 18:05* @Version 1.0*/
@Service
public class RedisService {private final RedisTemplate<String, Object> redisTemplate;private final StringRedisTemplate stringRedisTemplate;@Autowiredpublic RedisService(RedisTemplate<String, Object> redisTemplate, StringRedisTemplate stringRedisTemplate) {this.redisTemplate = redisTemplate;this.stringRedisTemplate = stringRedisTemplate;}// 保存对象public void set(String key, Object value) {redisTemplate.opsForValue().set(key, value);}// 保存对象并设置过期时间public void set(String key, Object value, long timeout, TimeUnit timeUnit) {redisTemplate.opsForValue().set(key, value, timeout, timeUnit);}// 获取对象public Object get(String key) {return redisTemplate.opsForValue().get(key);}// 删除对象public void delete(String key) {redisTemplate.delete(key);}// 设置 String 类型的值public void setString(String key, String value) {stringRedisTemplate.opsForValue().set(key, value);}// 获取 String 类型的值public String getString(String key) {return stringRedisTemplate.opsForValue().get(key);}// 批量删除public void deleteBatch(List<String> keys) {if (!CollectionUtils.isEmpty(keys)) {redisTemplate.delete(keys);}}// 设置 key 的过期时间public Boolean expire(String key, long timeout, TimeUnit timeUnit) {return redisTemplate.expire(key, timeout, timeUnit);}// 检查 key 是否存在public Boolean hasKey(String key) {return redisTemplate.hasKey(key);}
}

5.2单元测试类

package com.lazy.snail;import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class ApplicationTests {@Autowiredprivate RedisService redisService;@Testvoid contextLoads() {redisService.setString("name", "lazysnail");redisService.setString("email", "lazy_snail@aliyun.com");}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/16366.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

机器人控制技术、传感器技术、Wi-Fi无线通信技术、AI视觉应用教学和实训: 智能小车车臂教学平台

1、基本介绍 智能车臂教学平台在硬件上采用模块化设计&#xff0c;主控板、运动车体、机械臂、各类传感器等都可以进行拆卸操作&#xff1b;在接口上&#xff0c;采用标准拔插式设计&#xff0c;减少接线&#xff0c;方便组装。使用Wi-Fi与控制软件进行通信&#xff0c;支持遥…

ssm113ssm框架的购物网站+vue(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;网上超市系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本网上超市系统就是在这…

C++ 里面散发的咖喱味儿 - Currying函数式编程

C 里面散发的咖喱味儿 - Currying函数式编程 大家好&#xff0c;最近几篇都在聊C里面的函数式编程&#xff0c;今天我们继续就某一个点来深入聊一下&#xff0c;来聊聊在 C 中如何使用 std::bind 来实现函数式编程&#xff0c;尤其是柯里化&#xff08;Currying&#xff09;这…

【Gitee版】一篇教你如何快速入门git(详解)

前言--区分Git与Gitee Git 是一个强大的分布式版本控制系统&#xff0c;用于管理源代码。市面上有很多基于git的仓库网站&#xff0c;例如&#xff1a;GitHub、Gitee、GitCode等&#xff0c;它们之间的关系就好像是&#xff1a;git为基类&#xff0c;剩余为子类的样子。使用的…

Linux系统编程学习 NO.11——进程的概念(2)

谈谈进程的性质 进程的竞争性 由于CPU资源是稀缺的,进程数量是众多的。不可避免需要造成进程排队等待CPU资源的动作&#xff0c;内核的设计者为了让操作系统合理的去调度这这些进程&#xff0c;就产生了进程优先级的概念。设置合理的进程优先级能让不同进程公平的去竞争CPU资…

灵神 刷题DAY1

Python与java的刷题的区别 1. Python没有分号 2. Python不能return的时候赋值 3. Python没有小括号和花括号 4. Python的循环很奇怪&#xff0c;没有for(int i0;i<32;i)这种形式 而是直接用的是for i in range(n)这种 5. Python中没有 6. Python中没有&& 是an…

Nginx中使用keepalive实现保持上游长连接实现提高吞吐量示例与测试

场景 HTTP1 .1之后协议支持持久连接&#xff0c;也就是长连接&#xff0c;优点在于在一个TCP连接上可以传送多个HTTP请求和响应&#xff0c; 减少了建立和关闭连接的消耗和延迟。 如果我们使用了nginx去作为反向代理或者负载均衡&#xff0c;从客户端过来的长连接请求就会被…

【Spring AOP 原理】

首先AOP跟OOP(面向对象编程)、IOC(控制反转)一样都是一种编程思想 跟OOP不同, AOP是面向切面编程, 面对多个不具备继承关系的对象同时需要引入一段公共逻辑的时候, OOP就显得有点笨重了, 而AOP就游刃有余, 一个切面可以横跨多个类或者对象去执行公共逻辑, 极大的提升了开发效率…

Vue3集成搜索引擎智能提示API

需求&#xff1a; 如何在项目中实现像百度搜索框一样的智能提示效果&#xff0c;如下图所示&#xff1a; 相关知识&#xff1a; 下面是各厂商提供的免费API 厂商请求百度http://suggestion.baidu.com/su?wd中国&cbwindow.baidu.sug必应http://api.bing.com/qsonhs.as…

python3的基本数据类型:可变集合的用法

一. 简介 前面学习了 python3中的一种基本数据类型-集合&#xff0c;文章如下&#xff1a; python3的基本数据类型&#xff1a;集合的创建与分类-CSDN博客 本文继续学习 Python3中的集合&#xff0c;主要学习 可变集合的用法。 二. python3的基本类型&#xff1a;可变集合的…

从零开始:我的鸿蒙学习之旅(二)

前言 记录我在学习鸿蒙操作系统过程中的成长&#xff0c;旨在激励我自己&#xff0c;也希望能激发读者们的学习热情&#xff0c;一起愉快地探索鸿蒙开发的世界&#xff01; 我说说这几天的学习成果吧&#xff0c;将开发入门的第一部分的剩下小节以及第二部分的第一小结写完了…

SSM学习记录(一)之SSM整合

SSM学习记录&#xff08;一&#xff09;之SSM整合 一、SSM整合二、SSM整合的核心问题1、SSM需要几个IoC容器2、每个IoC容器对应哪些类型组件3、IoC容器之间的关系和调用方向4、具体有多少配置以及对应的容器的关系5、IoC初始化方式和配置位置 一、SSM整合 微观&#xff1a;将学…

【从理论到应用】HTTP请求响应详解 (请求数据格式,请求方式,Web开发中的体现)

目录 一.HTTP协议 二.HTTP请求数据格式 请求方式 三.Web开发中的HTTP请求与响应 接收HTTP请求 同一响应格式 四.使用第三方工具发送HTTP请求&#xff08;Apifox、postman、Yapi&#xff09; 一.HTTP协议 HTTP&#xff08;Hypertext Transfer Protocol&#xff0c;超…

猎板PCB罗杰斯板材的应用案例

以下是几个猎板 PCB 与罗杰斯板材结合的具体案例&#xff1a; 案例一&#xff1a;5G 通信基站天线 PCB 在 5G 通信基站的天线系统中&#xff0c;对高频信号的传输和处理要求极高。猎板 PCB 采用罗杰斯板材&#xff0c;凭借其稳定的低介电常数&#xff08;如 RO4003C 板材&…

基于Java Springboot快递物流管理系统

一、作品包含 源码数据库全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Layui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA 数据库&#xff1a;MySQL8.0 数据库管…

力扣662:二叉树的最大宽度

给你一棵二叉树的根节点 root &#xff0c;返回树的 最大宽度 。 树的 最大宽度 是所有层中最大的 宽度 。 每一层的 宽度 被定义为该层最左和最右的非空节点&#xff08;即&#xff0c;两个端点&#xff09;之间的长度。将这个二叉树视作与满二叉树结构相同&#xff0c;两端…

Servlet的使用

一.Servelt简介 1.为什么需要servlet:因为前端三件套无法操控数据库,即与用户进行交互操作 2.servlet由服务器端调用和执行的(由tomcat解析和调用的),由java语言编写,本质就是java类 3.功能强大,可以完成几乎所有的网站功能,按照Servlet规范开发 二.手动开发Servelt 1.Servl…

【嵌入式C语言】GCC概述+C语言编译过程

目录 前言1 课程介绍1.1 计算机程序语言的学习思路?1.2 基本程序设计思想:1.3 C语言工具的特性:1.4 推荐教材 2 GCC的使用及其常用选项介绍2.1 GCC概述gcc -vgcc -ogcc -v -o 2.2 C语言编译过程2.2.1 预处理2.2.2 编译2.2.3 汇编2.2.4 链接2.2.5 问题 2.3 宏的使用 前言 重新学…

C语言 数组排序 – 插入法排序 - C语言零基础入门教程

目录 一.简介二.数组插入法排序原理三.数组插入法排序实战四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.简介 经过前面的学习&#xff0c;我们已经学会了数组遍历&#xff0c;在开发中&#xff0c;我们经常回碰到对数组进行排序&#xff0c…