当前位置: 首页 > news >正文

深入理解SpringBoot(一)----SpringBoot的启动流程分析

1、SpringApplication 对象实例化

SpringApplication 文件

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {// 传递的source其实就是类Bootstrapreturn new SpringApplication(sources).run(args);// 实例化一个SpringApplication对象执行run方法
}

实例化的时候又会执行initialize 方法

private void initialize(Object[] sources) {// 这个source依旧是上文说的Bootstrap.class 类if (sources != null && sources.length > 0) {this.sources.addAll(Arrays.asList(sources));// 添加到source资源列表里面去}this.webEnvironment = deduceWebEnvironment();// 设置其是否为web环境setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 拆分为两步,一步是getSpringFactoriesInstances,再者就是set操作// set操作很简单,就是设置当前对象的初始化对象以及监听器this.mainApplicationClass = deduceMainApplicationClass();// 通过堆栈信息,推断 main方法的类对象为当前的主程序类
}private static final String[] WEB_ENVIRONMENT_CLASSES = { "javax.servlet.Servlet","org.springframework.web.context.ConfigurableWebApplicationContext" };private boolean deduceWebEnvironment() {for (String className : WEB_ENVIRONMENT_CLASSES) {// 遍历包含上述两个类名称的数组if (!ClassUtils.isPresent(className, null)) {// 一旦发现不存在该类,就立即返回 deduce 推断不是web环境return false;}}// 必须同时包含两个类,才推断出为web环境return true;
}

getSpringFactoriesInstances 方法操作

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {// 传递的type就是上面说的ApplicationContextInitializer.class以及ApplicationListener.class类// 类型以及参数目前都没有具体指ClassLoader classLoader = Thread.currentThread().getContextClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));// 通过SpringFactoriesLoader 获取对应的名称,具体详情可以看下面的代码块// 这点需要重点关注下!!!// 结果就是返回一个set集合List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);// 看样子就是创建一个实例的集合AnnotationAwareOrderComparator.sort(instances);// 然后通过AnnotationAwareOrderComparator 的排序规则跪实例集合进行排序// 排序就是看是否存在Order或者Priority注解,然后取得注解的值,排在集合前面return instances;
}private <T> List<T> createSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,Set<String> names) {List<T> instances = new ArrayList<T>(names.size());for (String name : names) {// 遍历上面取到的name 集合try {Class<?> instanceClass = ClassUtils.forName(name, classLoader);// 取到这个类名称的类Assert.isAssignable(type, instanceClass);Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);// 获取当前类的符合当前参数的构造器T instance = (T) BeanUtils.instantiateClass(constructor, args);// 利用反射的方式生成具体的对象instances.add(instance);}catch (Throwable ex) {throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);}}// 最后生成name映射的实例集合return instances;
}

SpringFactoriesLoader.loadFactoryNames 方法

public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {// 传递的factoryClass 就是上面的ApplicationContextInitializer、ApplicationListener.等String factoryClassName = factoryClass.getName();// 获取类的全名称try {Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));// 如果类加载器为null,则使用系统默认的方法,否则使用当前传递的类加载器读取// 当前类加载器可以获取到的所有文件路径为“META-INF/spring.factories” 的地址List<String> result = new ArrayList<String>();while (urls.hasMoreElements()) {// 迭代遍历urlURL url = urls.nextElement();Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));// 读取映射的spring.factories 文件的KV键值对,存放到properties对象中String factoryClassNames = properties.getProperty(factoryClassName);// 类似于map一般,获取对应的值result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));// 对值使用逗号分隔,生成list,然后去重添加到result}// 总结下来就是遍历当前类环境中的所有路径为“META-INF/spring.factories”的文件// 读取文件,然后获取k为当前类名称的所有值,然后存储到set中返回return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);}
}

到这里整个的initialize操作就已经清楚了,通过类加载器可获取的所有为“META-INF/spring.factories” 的地址的文件内容,然后获取key为ApplicationContextInitializer.class以及ApplicationListener.class的类名称的值集合
然后依次就行实例化,最后排序返回,最后保存到当前对象的初始化集合以及监听器集合中,便于后续操作
需要注意到SpringFactoriesLoader.loadFactoryNames 后面很多地方都需要使用该方法去获取相关内容
当然现在只是完成了SpringApplication构造器里面的方法,还剩下后面的run(args)方法执行
如下代码块就是SpringBoot的执行过程(最后的套路依旧是Spring Framework的执行策略)

利用SPI机制扫描 META-INF/spring.factories 这个文件,并且加载 ApplicationContextInitializer、ApplicationListener 接口实例。
1、ApplicationContextInitializer 这个类当springboot上下文Context初始化完成后会调用
2、ApplicationListener 当springboot启动时事件change后都会触发

总结:上面就是SpringApplication初始化的代码,new SpringApplication()没做啥事情 ,利用SPI机制主要加载了META-INF/spring.factories 下面定义的事件监听器接口实现类

2、SpringApplication的run方法启动

public ConfigurableApplicationContext run(String... args) {// 这是个计时器StopWatch stopWatch = new StopWatch();stopWatch.start();// 记录当前服务开始启动ConfigurableApplicationContext context = null;// 上下文context,非常关键FailureAnalyzers analyzers = null;configureHeadlessProperty();// 给系统设置headless属性值,就是设置了一些环境变量SpringApplicationRunListeners listeners = getRunListeners(args);// 获取事件监听器SpringApplicationRunListener类型,并且执行starting()方法// 就是通过SpringFactoriesLoader 获取到所有SpringApplicationRunListener.class的对象// 其中args是用来进行实例化SpringApplicationRunListener对应的对象的构造器参数// 最后返回listener是整个系统的监听器listeners.starting();// 监听器开始执行try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 默认程序参数ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);// 准备运行的环境上下文Banner printedBanner = printBanner(environment);// 打印banner,默认输出当前springboot版本等内容,可以自定义设置文本或者图片// 具体看下面的方法详解context = createApplicationContext();// 创建SpringBoot最重要的上下文容器analyzers = new FailureAnalyzers(context);// 分析上下文出现问题的点,便于使用者可以直观的发现问题出现在哪里// 其实套路类似,就是使用SpringFactoriesLoader获取所有的FailureAnalyzer实例对象,然后设置其bean工厂为context的bean工厂上下文prepareContext(context, environment, listeners, applicationArguments,printedBanner);// 看名称就是对context的前置准备工作,细节在后面说refreshContext(context);// 切入到spring framework的方式去完成context内容的装载// 如果需要注册终止钩子,则注册一个afterRefresh(context, applicationArguments);// 基本上认为springboot所需的服务都加载完成,进行最后的处理操作// 里面常用的就是CommandLineRunnerlisteners.finished(context, null);// 监听器的启动结束事件,stopWatch.stop();// 表示SpringBoot服务启动步骤完成,统计下启动时间等操作if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);// 打印SpringBoot启动成功的消息,例如 Started xxx in 12.4 seconds 等信息}return context;}catch (Throwable ex) {handleRunFailure(context, listeners, analyzers, ex);// 启动失败了就会输出Application startup failed 日志// 并且会输出具体的错误内容信息throw new IllegalStateException(ex);}
}private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// Create and configure the environmentConfigurableEnvironment environment = getOrCreateEnvironment();// 如果当前环境值不为null,直接返回// 否则根据上文推断出的webEnvironment boolean 值 生成对象的环境对象// 当为true的时候,生成StandardServletEnvironment// 否则生成的是StandardEnvironmentconfigureEnvironment(environment, applicationArguments.getSourceArgs());listeners.environmentPrepared(environment);if (!this.webEnvironment) {// 如果不是web的环境,再对当前的环境进行包装,生成一个新的运行环境对象environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}return environment;
}private Banner printBanner(ConfigurableEnvironment environment) {// 参数environment就是上面生成的环境对象if (this.bannerMode == Banner.Mode.OFF) {// 如果设置了banner关闭模式,则不进行打印输出操作return null;}ResourceLoader resourceLoader = this.resourceLoader != null ? this.resourceLoader: new DefaultResourceLoader(getClassLoader());// 资源加载器生成SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);// 后续使用SpringApplicationBannerPrinter 类的print进行输出操作if (this.bannerMode == Mode.LOG) {// 打印模式,如果是log则输出到log中,否则输出到终端中return bannerPrinter.print(environment, this.mainApplicationClass, logger);}return bannerPrinter.print(environment, this.mainApplicationClass, System.out);// 大致操作就是先看是否存在自定义的图片类型或者文字类型 banner,如果有就优先确定banner对象// 否则就默认使用SpringBootBanner的banner(这个里面就包含了常规的springboot输出内容)// 然后解析banner的资源,得出将要输出的字符串内容(利用日志直接输出),存储到PrintedBanner
}public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework."+ "boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext";public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context."+ "annotation.AnnotationConfigApplicationContext";protected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try {contextClass = Class.forName(this.webEnvironment? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);// 如果是web环境,则使用AnnotationConfigEmbeddedWebApplicationContext// 否则就使用AnnotationConfigApplicationContext}catch (ClassNotFoundException ex) {throw new IllegalStateException("Unable create a default ApplicationContext, "+ "please specify an ApplicationContextClass",ex);}}return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);// 直接通过类,反射生成无构造参数的对象,一般情况就是AnnotationConfigEmbeddedWebApplicationContext对象了
}private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// 传递上下文、环境、上下文参数等数据context.setEnvironment(environment);postProcessApplicationContext(context);// 前置处理context上下文,包含了beanNameGenerator和resourceLoader// 其中beanNameGenerator 可以自定义规则约定bean的名称功能applyInitializers(context);// 应用ApplicationContextInitializer去初始化完成对context的操作// 具体的ApplicationContextInitializer对象就是在SpringApplication对象的构造方法中实例化创建的// 可以给context添加额外的操作,同时也可以很方便的自定义完成自己需要的功能listeners.contextPrepared(context);// 执行contextPrepared 上下文准备工作的事件if (this.logStartupInfo) {// 日志启动标志位,默认为truelogStartupInfo(context.getParent() == null);logStartupProfileInfo(context);// 明确当前执行的主函数log,输出SpringBoot的开始启动信息}// 注册springApplicationArguments 这个bean到context中去context.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments);if (printedBanner != null) {context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);// 同样是注册,打印早就完成了}// Load the sourcesSet<Object> sources = getSources();// 一般情况下这个source就是SpringBoot 启动的主类Class,注意不是实例对象Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[sources.size()]));// 把source也就是主类当做bean,加载到spring的容器中listeners.contextLoaded(context);// 监听器的上下文导入完成事件 执行
}private void callRunners(ApplicationContext context, ApplicationArguments args) {List<Object> runners = new ArrayList<Object>();runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());AnnotationAwareOrderComparator.sort(runners);// 从context获取ApplicationRunner和CommandLineRunner 对象// 然后按照对应的规则进行排序for (Object runner : new LinkedHashSet<Object>(runners)) {if (runner instanceof ApplicationRunner) {callRunner((ApplicationRunner) runner, args);}if (runner instanceof CommandLineRunner) {callRunner((CommandLineRunner) runner, args);}// 分别执行各自的run方法}// 一般情况,我们如果需要在SpringBoot加载完成后需要完成一些自定义操作就是注册// ApplicationRunner或者CommandLineRunner 的bean对象,然后自定义实现run方法即可
}

3、总结

就SpringBoot的启动整个过程而已,还是很清晰的,SpringBoot的套用SpringFramework的机制,为我们自定义实现功能提供了很好的便利,整个的SpringBoot就是重新包装了一个SpringFramework。
1、new了一个SpringApplication对象,使用SPI技术加载加载 ApplicationContextInitializer、ApplicationListener 接口实例

2、调用SpringApplication.run() 方法

3、调用createApplicationContext()方法创建上下文对象,创建上下文对象同时会注册spring的核心组件类(ConfigurationClassPostProcessor 、AutowiredAnnotationBeanPostProcessor 等)。

4、调用refreshContext() 方法启动Spring容器和内置的Servlet容器(tomcat),内置的Servlet容器就是在onRefresh() 方法里面启动的


引用(本文章只供本人学习以及学习的记录,如有侵权,请联系我删除)

SpringBoot 启动过程源码分析
SpringBoot启动流程总结

最后编辑于:2024-09-09 20:07:32


喜欢的朋友记得点赞、收藏、关注哦!!!

相关文章:

深入理解SpringBoot(一)----SpringBoot的启动流程分析

1、SpringApplication 对象实例化 SpringApplication 文件 public static ConfigurableApplicationContext run(Object[] sources, String[] args) {// 传递的source其实就是类Bootstrapreturn new SpringApplication(sources).run(args);// 实例化一个SpringApplication对象执…...

MySql基础-单表操作

1. MYSQL概述 1.1 数据模型 关系型数据库 关系型数据库(RDBMS)&#xff1a;建立在关系模型基础上&#xff0c;由多张相互连接的二维表组成的数据库。 特点&#xff1a; 使用表存储数据&#xff0c;格式统一&#xff0c;便于维护 使用SQL语言操作&#xff0c;标准统一&…...

【STM32系统】基于STM32设计的SD卡数据读取与上位机显示系统(SDIO接口驱动、雷龙SD卡)——文末资料下载

基于STM32设计的SD卡数据读取与上位机显示系统 演示视频&#xff1a; 基于STM32设计的SD卡数据读取与上位机显示系统 简介&#xff1a;本研究的主要目的是基于STM32F103微控制器&#xff0c;设计一个能够读取SD卡数据并显示到上位机的系统。SD卡的数据扇区读取不仅是为了验证存…...

SpringBoot开发——整合Redis

文章目录 1、创建项目&#xff0c;添加Redis依赖2、创建实体类Student3、创建Controller4、配置application.yml5、整合完成 Redis ( Remote Dictionary Server &#xff09;是一个开源的内存数据库&#xff0c;遵守 BSD 协议&#xff0c;它提供了一个高性能的键值&#xff08…...

OpenCV结构分析与形状描述符(17)判断轮廓是否为凸多边形的函数isContourConvex()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 测试轮廓的凸性。 该函数测试输入的轮廓是否为凸的。轮廓必须是简单的&#xff0c;即没有自相交。否则&#xff0c;函数的输出是不确定的。 cv:…...

P5425 [USACO19OPEN] I Would Walk 500 Miles G

*原题链接* 很离谱的题。首先可以想到暴力连边&#xff0c;整个图为一个完全图&#xff0c;将所有的边选出来&#xff0c;然后从小到大一条条加入&#xff0c;当剩下集合数量 <K 的时候就结束。答案为加入的最后一条边的大小。如果用prim算法的话时间复杂度为。足以通过此题…...

Java高级Day41-反射入门

115.反射 反射机制 1.根据配置文件re.properties指定信息&#xff0c;创建Cat对象并调用hi方法 SuppressWarnings({"all"}) public class ReflectionQuestion {public static void main(String[] args) throws IOException {//根据配置文件 re.properties 指定信息…...

在Linux系统上使用Docker部署java项目

一.使用Docker部署的好处&#xff1a; 在Linux系统上使用Docker部署项目通常会大大简化部署流程&#xff0c;因为Docker可以将应用程序及其依赖打包到一个独立的容器中。 Docker打包应用程序时会将其与所有依赖项&#xff08;操作系统、库等&#xff09;一起打包。这样&#…...

【C++】标准库IO查漏补缺

【C】标准库 IO 查漏补缺 文章目录 系统I/O1. 概述2. cout 与 cerr3. cerr 和 clog4. 缓冲区5. 与 printf 的比较 系统I/O 1. 概述 标准库提供的 IO 接口&#xff0c;包含在 iostream 文件中 输入流: cin输出流&#xff1a;cout / cerr / clog。 输入流只有一个 cin&#x…...

python简单易懂的lxml读取HTML节点及常用操作方法

python简单易懂的lxml读取HTML节点及常用操作方法 1. 初始化和基本概念 lxml 是一个强大的pyth库&#xff0c;用于处理XML和HTML文档。它提供了类似BeautifulSoup的功能&#xff0c;但性能更高。在使用lxml时&#xff0c;通常会先解析HTML或XML文档&#xff0c;得到一个Eleme…...

Java | Leetcode Java题解之第406题根据身高重建队列

题目&#xff1a; 题解&#xff1a; class Solution {public int[][] reconstructQueue(int[][] people) {Arrays.sort(people, new Comparator<int[]>() {public int compare(int[] person1, int[] person2) {if (person1[0] ! person2[0]) {return person2[0] - perso…...

安卓获取apk的公钥,用于申请app备案等

要申请app的icp备案等场景&#xff0c;需要app的 证书MD5指纹和公钥&#xff0c;示例如下&#xff1a; 步骤1&#xff1a;使用keytool从APK中提取证书 1. 打开命令行&#xff0c;cd 到你的apk目录&#xff0c;如&#xff1a;app/release 2. 解压APK文件&#xff1a; unzip yo…...

【leetcode_python】杨辉三角

给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1 输出: [[1]] 方案&#…...

Parallels Desktop 20 for Mac中文版发布了?会哪些新功能

Parallels Desktop 20 for Mac 正式发布&#xff0c;完全支持 macOS Sequoia 和 Windows 11 24H2&#xff0c;并且在企业版中引入了全新的管理门户。 据介绍&#xff0c;新版本针对 Windows、macOS 和 Linux 虚拟机进行了大量更新&#xff0c;最大的亮点是全新推出的 Parallels…...

SpringBoot整合SSE-灵活管控连接

SpringBoot整合SSE(管控连接) 1、sse单向通信整成逻辑双向通信。 2、轻量级实现端对端信息互通。 3、避免繁琐配置学习。 核心点通过记录连接码和心跳检测实现伪双向通道,避免无效连接占用过多内存。 服务器推送(Server Push)技术允许网站和应用在有新内容可用时主动向用户…...

挖矿木马-Linux

目录 介绍步骤 介绍 1、挖矿木马靶机中切换至root用户执行/root目录下的start.sh和attack.sh 2、题目服务器中包含两个应用场景&#xff0c;redis服务和hpMyAdmin服务&#xff0c;黑客分别通过两场景进行入侵&#xff0c;入侵与后续利用线路路如下&#xff1a; redis服务&…...

【leetcode——415场周赛】——python前两题

3289. 数字小镇中的捣蛋鬼 数字小镇 Digitville 中&#xff0c;存在一个数字列表 nums&#xff0c;其中包含从 0 到 n - 1 的整数。每个数字本应 只出现一次&#xff0c;然而&#xff0c;有 两个 顽皮的数字额外多出现了一次&#xff0c;使得列表变得比正常情况下更长。 为了…...

【CSS in Depth 2 精译_029】5.2 Grid 网格布局中的网格结构剖析(上)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…...

ZYNQ LWIP(RAW API) TCP函数学习

1 LWIP TCP函数学习 tcp_new()–新建控制块 这个函数用于分配一个TCP控制块,它通过tcp_alloc()函数分配一个TCP控制块结构来存储TCP控制块的数据信息, 如果没有足够的内容分配空间,那么tcp_alloc()函数就会尝试释放一些不太重要的TCP控制块, 比如就会释放处于TIME_WAIT、C…...

Spring Boot,在应用程序启动后执行某些 SQL 语句

在 Spring Boot 中&#xff0c;如果你想在应用程序启动后执行某些 SQL 语句&#xff0c;可以利用 spring.sql.init 属性来配置初始化脚本。这通常用于在应用启动时创建数据库表、索引、视图等&#xff0c;或者填充默认数据。data-locations 和 schema-locations 指定了 SQL 脚本…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

大型活动交通拥堵治理的视觉算法应用

大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动&#xff08;如演唱会、马拉松赛事、高考中考等&#xff09;期间&#xff0c;城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例&#xff0c;暖城商圈曾因观众集中离场导致周边…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

redis和redission的区别

Redis 和 Redisson 是两个密切相关但又本质不同的技术&#xff0c;它们扮演着完全不同的角色&#xff1a; Redis: 内存数据库/数据结构存储 本质&#xff1a; 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能&#xff1a; 提供丰…...