深入解析Spring Boot启动流程:从SpringApplication.run()到应用就绪

news2026/5/16 9:18:16
1. 项目概述为什么我们需要深入理解SpringApplication.run()如果你是一个Java开发者尤其是使用Spring Boot框架的那么SpringApplication.run(YourApplication.class, args)这行代码对你来说一定不陌生。它几乎是每个Spring Boot应用的启动入口就像汽车的点火开关。但你是否想过按下这个“开关”后引擎盖下究竟发生了什么从读取配置、创建容器、加载Bean到启动内嵌的Web服务器这一系列复杂而精密的操作是如何串联起来的很多开发者包括早期的我都曾满足于“它会自动帮我启动应用”这个黑盒认知。直到线上遇到一个诡异的启动失败问题日志只抛出一个模糊的“Bean创建异常”而堆栈信息深不见底我才意识到不理解启动流程排查问题就像在迷宫里摸黑走路。理解SpringApplication.run()的大致流程绝非纸上谈兵。它能让你高效排错当应用启动失败时你能快速定位问题发生在哪个阶段是环境准备、Bean定义加载还是Bean初始化而不是盲目地四处翻日志。深度定制当你需要干预启动过程比如在特定阶段执行一些初始化代码、加载外部配置或者自定义内嵌服务器行为时你知道该在哪里“挂钩子”。掌握框架精髓Spring Boot“约定大于配置”和“自动装配”的核心魔法很大程度上是在这个启动流程中实现的。理解它是理解Spring Boot设计哲学的关键。本文将带你深入SpringApplication.run()方法内部以一名一线开发者的视角拆解其从启动到就绪的完整生命周期。我们会避开过于底层的源码细节聚焦于核心阶段、关键组件和实际影响并穿插我在实践中踩过的坑和总结的技巧。无论你是想解决启动难题还是想更优雅地驾驭Spring Boot这篇文章都将为你提供一张清晰的“启动地图”。2. 启动流程全景与核心阶段拆解SpringApplication.run()的旅程可以清晰地划分为几个大的阶段。它不是一蹴而就的而是一个层层递进、环环相扣的过程。为了让你有个全局观我们先俯瞰全貌然后再深入每个阶段的细节。整个流程的核心目标是创建并刷新一个ApplicationContext应用上下文即Spring容器。围绕这个目标Spring Boot设计了一套标准化的启动模板。其主要阶段如下图所示我们会在脑海中构建避免使用图表代码第一阶段启动前的“战前准备” (Initialization Phase)这个阶段发生在SpringApplication实例化时。当你调用SpringApplication.run(YourApplication.class, args)的静态方法时内部首先会创建一个SpringApplication实例。在这个过程中它会做几件关键事推断应用类型判断你是要启动一个普通的非Web应用ApplicationType.NONE、一个基于Servlet的Web应用ApplicationType.SERVLET还是一个响应式Web应用ApplicationType.REACTIVE。这个判断决定了后续创建哪种类型的ApplicationContext。加载“引导器” (Initializers)从spring.factories配置文件中加载所有ApplicationContextInitializer。这些初始化器允许我们在容器刷新refresh之前对ApplicationContext进行一些编程式的配置。比如添加一些自定义的属性源。加载“监听器” (Listeners)同样从spring.factories加载所有ApplicationListener。这些监听器是Spring事件驱动模型的核心它们会监听启动过程中发布的各类事件如ApplicationStartingEvent,ApplicationPreparedEvent等让我们有机会在特定时间点插入自定义逻辑。推断主配置类确定哪个是包含SpringBootApplication或Configuration注解的“主类”。实操心得很多自定义的starter起步依赖会利用spring.factories在这里注册自己的初始化器或监听器以实现“开箱即用”的效果。当你自己写starter时这是关键的扩展点。第二阶段容器的“诞生与成长” (Run Phase - Context Creation Refresh)这是最核心、最复杂的阶段发生在run()方法内部。它又可以细分为多个子步骤我们按顺序来看2.1 启动计时与监听器通知启动一个StopWatch开始计时并立即发布ApplicationStartingEvent事件。任何监听了此事件的ApplicationListener都会收到通知。这是整个生命周期中最早能被我们捕获的事件此时连ApplicationContext都还没创建。2.2 准备环境 (Prepare Environment)创建并配置应用运行所需的Environment对象。Environment是Spring抽象出来管理配置的接口它统一了各种属性源Property Sources如命令行参数、系统属性、操作系统环境变量、以及我们的application.properties或application.yml文件。关键动作它会遍历所有PropertySourceLoader属性源加载器加载默认路径下的配置文件。同时它会处理spring.profiles.active指定的激活配置文件将对应配置文件如application-dev.yml的属性也加载进来并覆盖默认配置。2.3 创建应用上下文 (Create ApplicationContext)根据第一阶段推断出的应用类型实例化对应的ApplicationContext。对于最常见的Servlet Web应用创建的是AnnotationConfigServletWebServerApplicationContext。这个容器支持基于注解的配置并且内嵌了一个Web服务器。2.4 准备上下文 (Prepare Context)在容器刷新之前对其进行一些前置配置将准备好的Environment设置到上下文中。执行之前加载的所有ApplicationContextInitializer的initialize方法。发布ApplicationContextInitializedEvent事件。向容器中注册一些特殊的单例Bean比如命令行参数ApplicationArguments以及我们传入的“主类”它会被当作一个BeanDefinition注册进去这是组件扫描的起点。发布ApplicationPreparedEvent事件。这个事件发生时Bean定义已经加载完毕但Bean实例还未创建是进行一些最后时刻的Bean定义修改如动态注册Bean的理想时机。2.5 刷新上下文 (Refresh Context)调用上下文的refresh()方法。这是整个启动流程中最核心、最重量级的一步它触发了Spring容器经典的IoC控制反转和DI依赖注入流程。AbstractApplicationContext.refresh()是一个模板方法定义了标准流程主要包括prepareRefresh(): 设置启动时间、激活状态初始化属性源。obtainFreshBeanFactory(): 获取或刷新内部的BeanFactoryBean工厂。prepareBeanFactory(): 配置BeanFactory的标准特性如类加载器、后置处理器等。postProcessBeanFactory(): 这是一个空方法子类可以覆盖它在Bean定义加载之前对BeanFactory进行后置处理。invokeBeanFactoryPostProcessors():关键步骤调用所有BeanFactoryPostProcessor。这包括ConfigurationClassPostProcessor: 它负责处理所有Configuration类解析ComponentScan进行组件扫描找到所有Component,Service,Repository,Controller等注解的类并注册为Bean定义、Import、Bean等方法是Spring Boot自动装配的魔法发生地。EnableAutoConfiguration的秘密就在这里被解开spring.factories中定义的自动配置类被加载、筛选根据Conditional条件注解、并应用。其他自定义的BeanFactoryPostProcessor。registerBeanPostProcessors(): 注册BeanPostProcessor。这些处理器会在Bean实例化、初始化的前后介入进行代理增强如AOP、属性注入等。initMessageSource(): 初始化国际化消息源。initApplicationEventMulticaster(): 初始化应用事件广播器。onRefresh(): 一个模板方法。对于Web应用ServletWebServerApplicationContext会覆盖此方法在这里创建并启动内嵌的Web服务器如Tomcat、Jetty、Undertow。registerListeners(): 将事件监听器注册到广播器。finishBeanFactoryInitialization():另一个关键步骤初始化所有剩余的单例Bean非懒加载的。这里会实例化Bean解决依赖关系调用初始化方法如PostConstruct、InitializingBean.afterPropertiesSet以及应用BeanPostProcessor。finishRefresh(): 完成刷新发布ContextRefreshedEvent事件。此时容器已完全就绪。第三阶段启动后的“收尾与就绪” (After Refresh Phase)容器刷新完成后run()方法还会执行一些收尾工作调用所有CommandLineRunner和ApplicationRunner的run方法。这两个接口允许我们在应用完全启动后执行一些特定的逻辑比如加载初始数据、启动后台线程等。它们的执行顺序可以通过Order注解控制。发布ApplicationStartedEvent事件。最后发布ApplicationReadyEvent事件。这个事件标志着应用已完全启动可以对外提供服务了。健康检查接口/actuator/health通常在此事件之后才会返回UP状态。至此SpringApplication.run()的整个生命周期才宣告结束你的应用进入运行状态等待处理请求。3. 核心细节解析与关键扩展点剖析了解了宏观流程我们再来深挖几个对开发者而言至关重要的核心细节和扩展点。理解这些你就能真正地“介入”和“掌控”启动过程。3.1 事件驱动模型在关键时刻“挂钩子”Spring Boot的启动过程是高度事件化的。我们之前提到了很多ApplicationEvent它们构成了一个清晰的生命周期钩子。你可以通过实现ApplicationListener接口或使用EventListener注解来监听这些事件。核心事件序列与用途事件类型发布时机典型用途ApplicationStartingEventrun()方法一开始任何处理之前最早的点可用于初始化非常早期的全局资源。ApplicationEnvironmentPreparedEventEnvironment已创建但尚未应用到Context在配置加载后、容器使用前动态添加或修改Environment中的属性。ApplicationContextInitializedEventApplicationContext已创建Initializers已调用但Bean定义未加载在Bean加载前对ApplicationContext进行最后的编程式配置。ApplicationPreparedEventBean定义已加载到容器但Bean实例未创建动态注册Bean定义的最后机会。常用于基于条件动态注册组件。ContextRefreshedEventApplicationContext刷新完成所有单例Bean已初始化容器就绪可在此执行一些依赖Spring容器的初始化逻辑。ApplicationStartedEventContextRefreshedEvent之后Runner执行之前标志应用已启动但Runner还未运行。ApplicationReadyEvent所有CommandLineRunner和ApplicationRunner执行完毕后应用完全就绪可安全接收请求。设置就绪标志、启动外部通知等。ApplicationFailedEvent启动过程中任何阶段发生异常时用于启动失败的日志记录、告警和资源清理。注意事项监听器的执行顺序可能会受到Order注解影响。另外在ApplicationPreparedEvent之前由于Bean尚未实例化监听器方法如果被EventListener标注在一个Bean的方法上则该Bean必须提前通过其他方式如Bean方法注册或者监听器本身不是一个Spring Bean较少见。3.2 自动装配的奥秘EnableAutoConfiguration如何工作这是Spring Boot“约定大于配置”的灵魂。关键在于EnableAutoConfiguration注解它通过Import(AutoConfigurationImportSelector.class)导入了选择器。加载候选配置AutoConfigurationImportSelector会从所有jar包的META-INF/spring.factories文件中读取org.springframework.boot.autoconfigure.EnableAutoConfiguration键对应的全限定类名列表。这就是一堆“自动配置类”。过滤与去重并不是所有候选类都会被加载。选择器会根据Conditional系列注解如ConditionalOnClass,ConditionalOnBean,ConditionalOnProperty进行过滤。例如只有当类路径下存在DataSource.class时数据源的自动配置类才会生效。同时会排除你在SpringBootApplication中通过exclude属性指定的类。配置类生效最终生效的自动配置类会被当作普通的Configuration类处理由ConfigurationClassPostProcessor解析。这些配置类中通常定义了大量的Bean方法并且条件化地创建了应用所需的组件如DataSource,JdbcTemplate,DispatcherServlet等。实操心得当你发现某个自动配置的功能没有按预期工作时首先检查对应的条件是否满足。例如Redis自动配置没生效可能是你忘了引入spring-boot-starter-data-redis依赖导致ConditionalOnClass(RedisConnectionFactory.class)不满足或者是application.yml中spring.redis.host配置缺失导致ConditionalOnProperty不满足。使用--debug模式启动应用可以在控制台看到所有自动配置类的评估报告positive matches, negative matches这是排查此类问题的利器。3.3 内嵌Web服务器的创建与启动对于Web应用onRefresh()阶段是魔法发生的地方。以Tomcat为例ServletWebServerApplicationContext会调用createWebServer()方法。它通过ServletWebServerFactory自动配置提供的比如TomcatServletWebServerFactory来创建一个WebServer。工厂会从Environment中读取server.port默认8080、server.servlet.context-path等配置。创建Tomcat实例配置连接器Connector并将应用自身作为一个ServletContext添加到Tomcat中。最后调用webServer.start()启动Tomcat。此时Tomcat的工作线程如Acceptor、Poller开始运行监听端口但应用尚未完全就绪ApplicationReadyEvent还未发布。踩坑记录有一次遇到应用启动后立即退出日志显示端口被占用。排查发现是在一个Configuration类的Bean方法中依赖了某个需要网络连接初始化的Bean而这个Bean的初始化抛出了连接超时异常。这个异常发生在finishBeanFactoryInitialization()阶段导致容器刷新失败进而触发了ApplicationFailedEvent。虽然Tomcat可能已经启动了但因为容器刷新失败整个run()方法异常退出JVM进程终止。关键点Web服务器启动(onRefresh)在Bean初始化(finishBeanFactoryInitialization)之前。如果Bean初始化失败即使服务器启动了应用也会退出。4. 自定义与干预启动流程的实战技巧理解了原理我们就能在合适的时机做正确的事。下面分享几个常见的自定义场景和实操代码片段。4.1 自定义ApplicationContextInitializer假设我们需要在环境准备完成后动态地从数据库或配置中心加载一些属性。import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import java.util.HashMap; import java.util.Map; public class CustomPropertySourceInitializer implements ApplicationContextInitializerConfigurableApplicationContext { Override public void initialize(ConfigurableApplicationContext applicationContext) { ConfigurableEnvironment environment applicationContext.getEnvironment(); // 模拟从外部源如数据库、HTTP接口加载配置 MapString, Object customProperties fetchPropertiesFromExternalSource(); MapPropertySource customPropertySource new MapPropertySource(customPropertySource, customProperties); // 将自定义属性源添加到环境的最前面优先级最高 environment.getPropertySources().addFirst(customPropertySource); System.out.println(自定义属性源已加载优先级最高。); } private MapString, Object fetchPropertiesFromExternalSource() { // 这里实现你的远程获取逻辑 MapString, Object map new HashMap(); map.put(custom.key, value-from-db); return map; } }要让这个初始化器生效你需要在META-INF/spring.factories文件中注册适用于打包成jar的starterorg.springframework.context.ApplicationContextInitializercom.yourpackage.CustomPropertySourceInitializer或者在Spring Boot主类中通过SpringApplication.addInitializers()方法添加适用于主应用SpringBootApplication public class YourApplication { public static void main(String[] args) { SpringApplication app new SpringApplication(YourApplication.class); app.addInitializers(new CustomPropertySourceInitializer()); app.run(args); } }4.2 利用ApplicationListener执行特定阶段任务假设我们需要在应用上下文准备好之后ContextRefreshedEvent但Web服务器完全就绪之前ApplicationReadyEvent执行一些数据预加载。import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.stereotype.Component; Component public class DataPreloader implements ApplicationListenerContextRefreshedEvent { Override public void onApplicationEvent(ContextRefreshedEvent event) { // 确保是根应用上下文的事件避免子上下文如Spring MVC触发多次 if (event.getApplicationContext().getParent() null) { System.out.println(应用上下文已刷新开始预加载核心数据...); // 调用你的数据加载服务 // dataLoadingService.loadEssentialData(); System.out.println(核心数据预加载完成。); } } }使用EventListener注解是更现代的方式import org.springframework.context.event.EventListener; import org.springframework.stereotype.Component; Component public class DataPreloader { EventListener public void handleContextRefresh(ContextRefreshedEvent event) { if (event.getApplicationContext().getParent() null) { // 你的预加载逻辑 } } }4.3 使用CommandLineRunner和ApplicationRunner这两个接口用于在应用完全启动后执行一些一次性任务。它们非常相似区别在于ApplicationRunner接收的ApplicationArguments对象对命令行参数做了更结构化的解析支持--keyvalue格式。import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; Component Order(1) // 通过Order控制执行顺序值越小优先级越高 public class MyCommandLineRunner implements CommandLineRunner { Override public void run(String... args) throws Exception { System.out.println(CommandLineRunner执行原始参数: String.join(, , args)); // 执行你的启动任务例如清理临时文件、发送启动通知等 } } Component Order(2) public class MyApplicationRunner implements ApplicationRunner { Override public void run(ApplicationArguments args) throws Exception { System.out.println(ApplicationRunner执行); System.out.println(非选项参数: args.getNonOptionArgs()); System.out.println(选项参数key: args.getOptionNames()); args.getOptionNames().forEach(key - System.out.println(key args.getOptionValues(key))); // 可以基于解析后的参数执行更复杂的逻辑 } }5. 常见启动问题排查与性能优化实战掌握了流程和扩展点我们来看看如何解决实际启动中遇到的问题并做一些优化。5.1 典型启动失败场景与排查路径启动失败的原因五花八门但按照流程阶段来排查可以事半功倍。问题1端口被占用 (WebServerException)现象APPLICATION FAILED TO START提示Port 8080 was already in use。排查使用命令netstat -ano | findstr :8080Windows或lsof -i:8080Linux/Mac找出占用进程。如果是旧进程未退出强制结束它。检查配置server.port是否被意外设置成了常用端口。进阶可能如果你的应用有多个Web服务器相关的自动配置被激活比如同时引入了Tomcat和Undertow的starter可能会造成冲突。检查依赖排除不需要的。问题2Bean创建失败 (BeanCreationException)现象启动时抛出BeanCreationException通常伴随Caused by说明具体原因如依赖的Bean不存在、构造器参数不匹配、PostConstruct方法抛出异常等。排查看堆栈最底层的Caused by这是根本原因。检查Bean的依赖确保被注入的Bean通过Autowired,Resource等已经正确声明Component,Service等并且能被扫描到不在ComponentScan范围外。检查配置属性如果Bean依赖ConfigurationProperties绑定的属性确保application.yml中的属性前缀和类型匹配没有拼写错误。检查条件注解如果是一个自动配置类提供的Bean检查其上的ConditionalOn...条件是否满足。使用--debug启动查看报告。检查循环依赖Spring能处理构造器循环依赖外的多数循环依赖但复杂情况仍可能导致问题。错误信息通常会提示“Requested bean is currently in creation”。需要审视设计使用Lazy注解或改用Setter/字段注入打破循环。问题3配置属性绑定失败 (BindException)现象Failed to bind properties under xxx to type com.example.XxxProperties。排查检查application.yml中对应前缀下的属性名是否与ConfigurationProperties类中的字段名一致支持kebab-case转camelCase。检查属性值的类型是否匹配如字符串赋给了整型字段。检查是否有必要的配置缺失而对应的字段没有设置默认值或不是Optional。问题4类找不到 (ClassNotFoundException/NoClassDefFoundError)现象启动时或调用特定功能时抛出。排查检查pom.xml或build.gradle确认相关依赖是否已正确引入作用域scope是否正确如provided和runtime的区别。执行mvn dependency:tree或gradle dependencies查看依赖树检查是否有版本冲突导致依赖被排除。如果是多模块项目检查模块间的依赖关系是否配置正确。5.2 启动性能优化实践随着应用规模变大启动速度可能变慢。以下是一些有效的优化思路1. 惰性初始化 (Lazy Initialization)Spring Boot 2.2 支持将所有Bean设置为懒加载。这意味着Bean只有在第一次被请求时才会创建和初始化而不是在启动时全部初始化。启用在application.yml中设置spring.main.lazy-initializationtrue或使用SpringApplication.setLazyInitialization(true)。利弊可以显著减少启动时间特别是对于有大量Bean的应用。但可能导致第一个请求的延迟变高因为需要现场初始化Bean。同时一些启动阶段的问题如配置错误可能会延迟到第一次请求时才暴露。2. 排除不必要的自动配置Spring Boot的自动配置很强大但如果你用不到某些功能排除它们可以节省加载和条件评估的时间。全局排除在主类SpringBootApplication注解中使用exclude属性。SpringBootApplication(exclude {DataSourceAutoConfiguration.class, RedisAutoConfiguration.class})通过配置排除在application.yml中使用spring.autoconfigure.exclude属性。spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration - org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration技巧使用--debug模式启动查看Negative matches部分那些被跳过的自动配置排除它们通常没有性能收益。重点排除那些Positive matches但你确实不需要的。3. 优化组件扫描路径默认情况下SpringBootApplication的ComponentScan会扫描主类所在包及其所有子包。如果项目结构庞大扫描范围过广会耗时。明确指定扫描包如果可能在主类上使用ComponentScan(basePackages {com.your.app.core, com.your.app.service})来精确指定需要扫描的包避免扫描第三方依赖或无用的目录。4. 使用Spring Boot 2.4 的配置文件新特性Spring Boot 2.4引入了对配置文件application.yml的层级合并和组功能使得配置更清晰。虽然对启动速度直接影响不大但清晰的配置有助于减少解析错误和提升可维护性间接避免因配置问题导致的启动失败重试。5. 分析启动耗时使用Spring Boot Actuator的startup端点需要引入spring-boot-starter-actuator并配置management.endpoints.web.exposure.includestartup可以获取详细的启动过程耗时分析定位到是哪个Bean的初始化、哪个PostProcessor消耗了最多时间从而进行针对性优化。理解SpringApplication.run()的流程就像掌握了应用的启动蓝图。它不仅能让你在问题出现时冷静应对更能让你在需要深度定制时游刃有余。从事件监听、自动装配原理到常见问题排查和性能优化每一个环节的深入理解都是你从Spring Boot使用者向驾驭者迈进的一步。下次当你再敲下那行启动代码时希望你的脑海中能清晰地浮现出这一幅生动的启动画卷。

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

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

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…