资讯动态

JavaFX+SpringBoot混搭启动报错:No auto configuration classes found原理与修复

发布时间:2026/10/4 5:09:26 来源:尧图企业网站定制
做 JavaFX 和 SpringBoot 混搭的工程最怕的不是业务逻辑写不出来而是项目一启动就卡在控制台那行红字上No auto configuration classes found in META-INF/spring.factories。这个报错我在自己的工具型客户端项目里踩到过后来帮朋友远程排查也遇到过好几次光看这行信息真的劝退尤其是 SpringBoot 版本升到 3.x 之后很多人连META-INF/spring.factories这个文件路径都找不到。今天就把这个问题从报错原理到修复步骤完整拆一遍顺便把 JavaFX 项目里容易踩的 classpath、资源和模块化坑都摆出来。这个问题的本质是 SpringBoot 的自动装配入口在启动阶段没有读到任何候选配置类。它可能发生在你新搭工程的第一跑也可能发生在 SpringBoot 从 2.x 升级到 3.x 之后甚至可能今天能启动、隔天 clean 一次就崩了。无论哪种场景排查思路是通用的先确认依赖在不在再看版本对应的自动配置文件格式对不对最后检查运行环境有没有把资源目录漏掉。下面我会按这个顺序来。1. 先搞清楚这个报错到底在说什么1.1 报错信息的准确拆解No auto configuration classes found in META-INF/spring.factories不是一个业务级别的异常它发生在SpringApplication.run()初始化阶段由AutoConfigurationImportSelector抛出。这个类做的事情就是去 classpath 里扫描 SpringBoot 自动配置的候选类集合。扫描不到任何东西就直接抛异常中断启动。为什么会抛这个异常来看 SpringBoot 2.x 的加载逻辑AutoConfigurationImportSelector.getCandidateConfigurations()通过SpringFactoriesLoader.loadFactoryNames()读取所有 jar 包中的META-INF/spring.factories文件找出 key 为org.springframework.boot.autoconfigure.EnableAutoConfiguration对应的全部 value 列表。如果这个列表是空的就抛出IllegalStateException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.也就是说这个报错跟你的业务代码基本无关问题集中在两个环节要么spring.factories文件根本没出现在运行时 classpath 中要么出现在 classpath 中了但文件里没有我们要的那个 key或者 key 对应的 value 为空、类不存在、格式解析失败。放到 JavaFX 场景里说就更好理解。你用 JavaFX 写界面用 SpringBoot 管理服务层对象启动入口可能是Application.launch()也可能是SpringApplication.run()。这时候项目结构往往不是 IDEA 默认生成的 SpringBoot 模板而是手工搭的 Maven/Gradle 工程。只要你漏了依赖、漏了资源文件或者运行配置里的 classpath 不完整自动配置加载链就会断在这里。1.2 自动装配的加载链一条很容易断的流水线为了让你后面排查有不慌的底气这里把整条加载链捋一遍。SpringBoot 启动时有几个关键动作创建SpringApplication实例记录主配置类。执行run()进入refreshContext()。解析配置类时ConfigurationClassPostProcessor发现主类上有EnableAutoConfiguration注解或被SpringBootApplication包含于是把任务交给AutoConfigurationImportSelector。AutoConfigurationImportSelector.selectImports()调getCandidateConfigurations()开始扫描候选自动配置类。SpringFactoriesLoader 把 classpath 下所有 jar 里的META-INF/spring.factories内容读出来筛选 key 为EnableAutoConfiguration的值。如果第三步没有返回任何候选类立刻抛异常。如果拿到了候选类Spring 再通过ConditionalOnClass、ConditionalOnMissingBean等条件注解逐一过滤留下真正需要加载的配置类注册成 Bean。从第 5 步开始就是最常断的地方。尤其注意 SpringBoot 2.7 到 3.x 这个分水岭2.7 仍然兼容读取spring.factories只是会打一个 deprecation 提示到了 SpringBoot 3.0官方彻底移除了从spring.factories读取自动配置类的行为改成了读取META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件。从 3.x 开始你就算在META-INF/spring.factories里写了EnableAutoConfigurationSpring 也“假装没看见”。注意SpringBoot 3.x 报同一句No auto configuration classes found...时它找的其实已经换了文件。这时候去改spring.factories是没有用的必须把自动配置类写进正确的.imports文件里。2. 为什么会报“没找到自动配置类”五类现场复盘2.1spring-boot-autoconfigure没进 classpath最常见很多 JavaFX 工程都是手工维护依赖的pom.xml 里可能只写了dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId version2.7.13/version /dependency这种情况下一般没事因为spring-boot-starter会传递依赖spring-boot-autoconfigure。有问题的是那些从旧项目改过来的代码或者仅引入了spring-boot-core、spring-context这类基础包根本不存在spring-boot-autoconfigurejar那自然找不到任何自动配置类。还有一种情况是直接把 SpringBoot 的 jar 手动拷到一个lib目录然后通过java -cp lib/* com.xxx.MainKt启动。如果你拷贝的时候漏掉spring-boot-autoconfigure-2.x.jar或者 IDEA 的 Artifacts 配置里没有把Maven: org.springframework.boot:spring-boot-autoconfigure加进输出启动就会丢这个异常。解决思路先去依赖树里确认真实情况。mvn dependency:tree -Dincludesorg.springframework.boot:spring-boot-autoconfigure输出里能看到spring-boot-autoconfigure:jar:2.7.13就说明依赖没问题接下来查运行配置。如果这里压根没有该 jar把依赖补上即可。2.2 版本太高配置文件路径已经换了这里特别对应“springboot版本太高”这个痛点。很多朋友从网上找了个 2.x 时代的老项目本地直接改成了 SpringBoot 3.x代码一行没动一启动就报错。原因是很明确的3.x 不再从spring.factories加载自动配置类SpringFactoriesLoader 在扫描时找不到默认的自动配置候选于是抛错但报错文案还沿用老文本只改了前半段的提示这就特别误导人。我给你整理一个版本对照SpringBoot 版本自动配置类声明位置是否还支持 spring.factories2.0 ~ 2.6META-INF/spring.factories支持2.7META-INF/spring.factories兼容支持有弃用提示3.0META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports不支持如果你项目里出现了版本混用比如主工程是 SpringBoot 3.2但某个第三方 starter 还在提供spring.factories这个第三方的自动配置就不会被自动加载。要么升级对方 starter要么自己在主工程里补.imports文件来声明那些你确实需要的自动配置类。2.3 资源文件被 Maven 过滤掉或根本没打包JavaFX 项目里很多人会配 Maven 的资源过滤来做配置文件占位符替换比如在pom.xml里这样写resources resource directorysrc/main/resources/directory filteringtrue/filtering /resource /resourcesfilteringtrue意味着 Maven 会把 resources 目录里的文本文件当模板处理替换${...}占位符。这个操作本身没问题但如果你同时指定了includes或者excludes就很容易把spring.factories、spring.handlers、spring.schemas这类文件漏掉。常见配置如下只保留了**/*.xmlresources resource directorysrc/main/resources/directory filteringtrue/filtering includes include**/*.xml/include /includes /resource /resources结果就是编译产物target/classes/META-INF/spring.factories根本没生成或生成了但被过滤成了空文件。Spring 读不到内容自然报错。2.4 JavaFX 特有的 classpath 坑JavaFX 运行方式跟普通 SpringBoot 应用不一样它通常由javafx.application.Application子类的launch()启动或者在start()里调SpringApplication.run()。这里有个典型问题IDEA 新建 JavaFX 模板工程时默认的 Run Configuration 只是Application类型不会主动使用 Maven 依赖管理。如果你直接用这个配置运行classpath 里只有模块自己的target/classes和项目依赖里显式声明的那部分 jar。SpringBoot 的 jar 没被加载自然找不到自动配置类。更隐蔽的情况是module-info.java。新版 IDEA 创建 JavaFX 项目默认生成 Java 模块描述文件模块化部署对 classpath 的约束很严格SpringBoot 的老式类扫描会受限。JavaFX 模块可能依赖 javafx.controls但 SpringBoot 的自动装配类在 unnamed module 里两者互相不能随意访问。多数情况下JavaFX SpringBoot 这个组合建议先不搞模块化把module-info.java删掉以 classpath 方式运行能省掉很多脏活。还有javafx-maven-plugin的javafx:run这个插件在构建 classpath 时会把编译依赖加入但要注意 plugin 配置里的options如果你指定了--module-path和--add-modulesSpring Boot 相关 jar 不应放在 module-path 中否则可能出现类加载顺序问题。2.5 公共模块里的自动配置类没被带进主程序多模块工程里你把一个自定义自动配置类写在 common 模块中这个自动配置类的作用是给业务模块提供通用 Bean。按理说主程序依赖 common 模块Spring 就能在 common 的 jar 里找到META-INF/spring.factories。但你实际排查时经常发现common 模块的target/classes下面没有这个文件或者有文件但里面是空的。原因通常是编译顺序带来的资源漏拷。你可以在 common 模块下先手动确认ls -la target/classes/META-INF/如果连META-INF目录都没建那就是 Maven 配置或目录结构的问题。注意src/main/resources/META-INF/spring.factories不是src/main/java/META-INF/spring.factories。Java 源码目录下的非.java文件不会自动进入资源输出目录除非你在 pom 里显式配了resource指向src/main/java比如早期 MyBatis 项目的 Mapper XML 那种配置。一旦你配了resource指向 java 目录还可能把META-INF下不该带的文件也带进去两边混乱大概率会出幺蛾子。3. 完整修复步骤一套可以照抄的检查清单3.1 第 1 步确认 SpringBoot 版本和依赖状态不管报错多吓人先跑一次依赖树确认自动配置的 jar 是不是真的存在。mvn dependency:tree -Dincludesorg.springframework.boot重点看版本是否合理。如果版本是 3.x跳去检查.imports文件如果版本是 2.x检查spring.factories。同时确认没有版本冲突比如项目里同时存在spring-boot-autoconfigure-2.7.13.jar和spring-boot-autoconfigure-3.2.0.jar某些依赖树冲突会直接让SpringFactoriesLoader读到不同 jar 的META-INF/spring.factories合并结果这里面只要出现解析错误也会导致加载失败。依赖缺失的补救很简单。如果是纯 JavaFX SpringBoot 客户端不需要 web 容器引入最基础的 starter 即可dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter/artifactId version2.7.13/version /dependency如果项目非要手工指定spring-boot-autoconfigure那请连同spring-boot和spring-boot-starter-logging一起引入别只拉一个 jarSpringBoot 的日志初始化和上下文刷新在启动早期就会触发缺了别的 jar 会连环报错。3.2 第 2 步找到正确的自动配置文件运行 SpringBoot 2.x 的项目确认 jar 内的spring.factories存在并且包含目标 keyjar tf ~/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.7.13/spring-boot-autoconfigure-2.7.13.jar | grep spring.factories然后看内容里有没有org.springframework.boot.autoconfigure.EnableAutoConfigurationunzip -p ~/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.7.13/spring-boot-autoconfigure-2.7.13.jar META-INF/spring.factories对于 SpringBoot 3.x文件路径完全不同META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports查看方式类似只是文件名变长了。如果这两个文件都不存在说明spring-boot-autoconfigure这个 jar 本身就有问题可能是被手工裁剪过或者仓库里被污染了。建议把本地仓库里的相关目录删除再重新mvn -U clean package拉取一次。还有一个容易忽略的点如果你项目里已经有一个src/main/resources/META-INF/spring.factories它在编译后会出现在target/classes/META-INF/spring.factories。此时 IDE 和 Maven 它的内容会和所有依赖 jar 里的内容合并。如果这个文件里只有org.springframework.boot.autoconfigure.EnableAutoConfiguration也就是 key 存在value 为空合并后依然可能因为空值导致异常甚至会把别的 jar 里的自动配置值覆盖掉。这种空 key 文件要优先清理。3.3 第 3 步手动补一个 spring.factories 文件做兜底如果你确实写了自己的自动配置类比如com.example.javafx.config.JavafxAutoConfiguration并且项目依然运行在 SpringBoot 2.x可以在src/main/resources/META-INF/spring.factories里手动声明文件内容如下org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.javafx.config.JavafxAutoConfiguration这里需要注意格式细节key 必须是org.springframework.boot.autoconfigure.EnableAutoConfiguration不要漏掉EnableAutoConfiguration后面的空格和等号。value 是自动配置类的全限定类名。如果有多个类用英文逗号分隔行尾加\续行。反斜杠后面不能有空格否则解析会把空格带入类名导致ClassNotFoundException。类必须真的存在并且至少标注Configuration。自动配置类的基础写法如下package com.example.javafx.config; import com.example.javafx.launcher.FxApplicationLauncher; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration(proxyBeanMethods false) public class JavafxAutoConfiguration { Bean ConditionalOnMissingBean public FxApplicationLauncher fxApplicationLauncher() { return new FxApplicationLauncher(); } }如果是 SpringBoot 3.x不写spring.factories而是新建文件src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件内容每行一个类全限定名不需要等号com.example.javafx.config.JavafxAutoConfiguration注意2.7 也支持读取这个.imports文件所以如果你希望同一个项目既能跑 2.7 又能平滑升级 3.x可以直接两个文件都配。旧版读spring.factories时不会因为多了.imports文件而报错反过来也一样SpringBoot 3.x 只认.imports。3.4 第 4 步修正 Maven 资源过滤和打包配置首先检查pom.xml里的resources不要写死 include 列表。必须保留资源默认行为或者明确包含spring.factories和spring/**下的文件resources resource directorysrc/main/resources/directory filteringfalse/filtering /resource /resources如果你还需要对某些配置文件做占位符替换我建议只对特定目录过滤不要把整个src/main/resources全局过滤。可以这样resources resource directorysrc/main/resources/directory filteringfalse/filtering excludes exclude**/*.yml/exclude exclude**/*.yaml/exclude exclude**/META-INF/**/exclude /excludes /resource resource directorysrc/main/resources/directory filteringtrue/filtering includes include**/*.yml/include include**/*.yaml/include /includes /resource /resources这样既要避免META-INF下的自动配置文件和 services 文件被过滤又保留了对application.yml占位符替换的能力。修改完 pom 后必须重新执行mvn clean package。因为target/classes里可能残留旧的资源文件直接package不 clean坑的是你自己。编译完成后再去 target 里看一眼find target/classes -name *.imports -o -name spring.factories确保文件真实存在且内容非空。3.5 第 5 步修正 JavaFX 的运行配置和模块化设置如果你是在 IDEA 里直接右键运行 JavaFX 类报的错先不要怀疑代码先看 Run Configuration。进入Run - Edit Configurations找到你的 Application 配置确认Use classpath of module选的是正确的主模块。不要勾选Shorten command line里的JAR manifestJavaFX 启动器配合该选项很容易出现类加载问题。推荐用none或argfileIDEA 2020 默认。如果你的项目是 Maven 工程最好先用mvn javafx:run验证一次如果 Maven 跑得通而 IDEA 跑不通那就是 IDE 的 classpath 配置问题。关于module-info.java我的建议是 JavaFX SpringBoot 的组合项目去掉模块化。不是不能做是收益太低SpringBoot 的自动配置扫描和第三方库兼容在模块化下会遇到太多边界问题。真要模块化SpringBoot 官方文档都建议使用--add-opens和--add-modules做大量额外配置对普通工具型客户端来说不值当。如果项目使用了javafx-maven-plugin需要检查配置。以下是一个能正常工作的最小配置plugin groupIdorg.openjfx/groupId artifactIdjavafx-maven-plugin/artifactId version0.0.8/version configuration mainClasscom.example.javafx.Launcher/mainClass /configuration /plugin注意mainClass不能直接指向继承javafx.application.Application的类。这是 JavaFX 的一个老坑当主类继承Application时JavaFX 启动器会在main方法之前做一些 native 组件初始化如果你的main方法里同时调了SpringApplication.run()就会冲突。推荐的写法是额外写一个不含 JavaFX 组件的启动类里面调用Application.launch()public class Launcher { public static void main(String[] args) { Application.launch(FxApplication.class, args); } }Spring 容器放进FxApplication.init()或start()中public class FxApplication extends Application { private ConfigurableApplicationContext context; Override public void init() { context SpringApplication.run(FxApplication.class); } Override public void start(Stage primaryStage) throws Exception { // 从容器取 Controller / Service } Override public void stop() throws Exception { context.close(); } }这种启动方式能让 SpringBoot 的自动装配尽量不受 JavaFX 启动器干扰。很多网上报错都是因为在main方法里强行SpringApplication.run()又直接launch()导致初始化顺序混乱。4. 排查实录一个真实的 SpringBoot 3.x 升级案例4.1 现场症状与初步定位之前有个工具客户端项目原本是 SpringBoot 2.4.2 JavaFX 11一切正常。后来为了用一个新 SDK把 SpringBoot 整体升到 3.2.3。升级后一启动控制台第一行红字就是java.lang.IllegalStateException: No auto configuration classes found in META-INF/spring.factories. If you are using a custom packaging, make sure that file is correct.我看到这个第一反应是依赖树里 autoconfigure 版本是多少于是执行mvn dependency:tree -Dincludesorg.springframework.boot:spring-boot-autoconfigure结果输出是[INFO] | - org.springframework.boot:spring-boot-autoconfigure:jar:3.2.3:compile依赖没问题。再打开 autoconfigure jar 看文件结构jar tf ~/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/3.2.3/spring-boot-autoconfigure-3.2.3.jar | grep -E spring.factories|imports结果只有META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports没有META-INF/spring.factories。这时候我意识到项目里有个自定义 starter是几年前在那个工程里自己写的里面用老方式在src/main/resources/META-INF/spring.factories里声明了一个自动配置类。SpringBoot 升级后这个 old school 写法彻底失效了AutoConfigurationImportSelector在 3.x 里连读都不读这个 key于是报出“找不到自动配置类”。4.2 从 spring.factories 到 AutoConfiguration.imports跟朋友确认后他在自定义 starter 的src/main/resources/META-INF/spring.factories写的是org.springframework.boot.autoconfigure.EnableAutoConfiguration\ com.example.fx.common.config.CommonAutoConfiguration当时 2.4 时代跑得很稳。升级之后我在这个 starter 模块里新建了src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports内容一行com.example.fx.common.config.CommonAutoConfiguration同时删掉了原先的spring.factories里那行 EnableAutoConfiguration 配置不删也不报错但留着容易让人误以为还有效。4.3 最终改法改完重新打包主工程 clean package 后再启动依然报错。这次报的就不是 No auto configuration classes found 了而是ClassNotFoundException: com.example.fx.common.config.CommonAutoConfiguration。原因也简单自定义 starter 模块的 jar 没更新到本地仓库主工程依赖的还是旧的 jar。执行mvn -pl common-module install -DskipTests mvn clean package重新拉依赖后启动恢复正常。这个案例的关键教训是改完公共模块一定要重新 install而不是只改主工程。JavaFX 项目经常是手工管理多模块这类“漏 install”问题是排查半天都找不到原因的隐藏杀手。5. 常见问题速查与避坑心得5.1 高频问题对照表现象原因处理方式报错提示找不到META-INF/spring.factories中的类spring-boot-autoconfigure依赖缺失引入spring-boot-starter查依赖树SpringBoot 3.x 项目报同样错误自动配置类声明位置变成了.imports文件新建AutoConfiguration.imports不再依赖spring.factories手动写了spring.factories仍无效版本是 3.x或 key 名拼错、value 为空确认版本改成正确的 key并确保类存在且可加载只在 IDEA 运行时报错Maven 正常Run Configuration classpath 配置有误检查Use classpath of module调整 Shorten command linejavafx:run有报错启动类直接继承了 Application新增 Launcher 类调用Application.launch()自动配置文件在src/main/resources下但打包后没找到Mavenresources过滤配置错误改成filteringfalse或对META-INF/**排除过滤公共模块里有spring.factories主工程却读不到公共模块没有 install或打包时资源丢失重新mvn install检查公共模块 target/classes 下的文件启动时出现奇怪的ClassNotFoundException本地 Maven 仓库 jar 损坏或版本冲突删除 .m2 对应目录重新mvn -U拉取5.2 踩过几次坑后总结的几条习惯第一资源文件一律不参与 Maven 过滤。SpringBoot 的自动装配机制依赖META-INF下的一堆文本文件这些文件一旦被占位符替换逻辑污染轻则启动报错重则静默加载失败。我现在的习惯是全局filteringfalse只有application.yml这类明确需要环境区分配置的文件才单独开过滤。第二做 JavaFX SpringBoot 客户端优先选 SpringBoot 2.7.x。这个版本既能读spring.factories又能读.imports自定义 starter 的兼容性最好。如果你要用 SpringBoot 3.x那我建议把项目里自动配置的文件统一改成.imports风格不要留两份避免后续维护时被误导。第三写自动配置类必须加上条件注解。不要裸写Configuration就上最好结合ConditionalOnClass、ConditionalOnMissingBean控制生效范围。JavaFX 项目里不同模块可能在不同运行模式下加载条件不写全很容易在你换运行方式时冒出各种“Bean 冲突”或“类找不到”的连锁问题。第四排查这类启动异常严格按“依赖 - 文件 - 运行配置”的顺序来。不要一上来就去改代码很多时候代码根本没毛病就是环境缺了东西。mvn clean package后去target/classes看文件是否存在这一步能过滤掉 80% 的问题。第五如果你遇到的是自定义自动配置类失效考虑不用自动装配机制直接在启动类里手动注册也不是不可以的。比如在主启动类上显式加Import(CommonAutoConfiguration.class)这算是一个绕开spring.factories/.imports的兜底手段适合临时救火但不适合作为长期方案——你以后每加一个自动配置类都要手动 import很繁琐也失去了 SpringBoot 约定优于配置的意义。我在实际项目中最后保留的做法是JavaFX 客户端用 2.7.x 起步所有公共模块无论是否需要自动配置都同时创建spring.factories和AutoConfiguration.imports两个声明文件。前者虽然在新版本中会失效但对于团队里习惯了老写法的人来说看文件能知道这里有几个自动配置后者保证升级到 SpringBoot 3.x 时直接生效。每次改完公共模块第一件事不是跑主工程而是install到本地仓库然后确认target/classes里那份自动配置文件内容是完整的。养成这个习惯后这个报错基本不会再成为卡住项目启动的门槛。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑