程序员老鬼

震惊!SpringBoot 3.0 居然把 spring.factories 给整没了?!

最近在折腾 SpringBoot 3.0 项目的时候,我发现一个熟悉的老朋友悄悄不见了:spring.factories。用惯了这个自动配置神器的朋友,估计一开始都会有点懵:“我配置的自动装配类怎么没生效?”这事儿不怪你,是 SpringBoot 3.0 整了个大活儿:它把这个机制给“劝退”了,换成了一个叫 imports 的新机制。
说真的,这事儿对老项目迁移、还有开发习惯的影响还是挺大的。那为啥好好的 spring.factories 就不香了?我们就来一起唠唠这个事儿。

以前的 spring.factories 是干嘛的?

在老版本里,spring.factories 文件就像个万能插线板,咱要搞自动配置、监听器、自定义扩展啥的,统统往这个文件里一写,SpringBoot 启动时就能给你全都接好,非常省心。
你只需要在 META-INF/ 下搞个配置文件,然后写点内容,比如:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.FooConfig,\
com.example.BarConfig
Spring 启动的时候就会把这些类都拉出来注册,完事儿。
这种机制本质上其实是个“阉割版的 SPI”,就是 Java 自带的服务发现机制,只不过 Spring 加了点料。

那为啥现在不要它了?

原因说复杂也不复杂,说简单也不简单,主要是 SpringBoot 3.0 开始,目标有点不一样了,人家要跟 GraalVM 这位“高冷选手”搞好关系,而 spring.factories 正好成了“绊脚石”。
咱一点点说原因:

1. 启动性能堪忧

项目一大,依赖多了,spring.factories 每次启动都得去翻一遍所有 jar 包的配置,时间久了你会发现——这玩意儿真磨叽。SpringBoot 3.0 想要的是更快的启动速度,这个机制就有点拖后腿了。

2. 不适配模块化

Java 9 推出了模块化系统(JPMS),结果 spring.factories 还是靠类路径到处扫,跟人家模块隔离的理念完全对不上号。你说它不合群,它还挺倔强。

3. 动态能力太弱

虽然 spring.factories 可以配合 @Conditional 注解搞点条件加载,但问题是所有类都得先加载进内存才能判断条件,效率感人。还不如一开始就别加载,让系统自己判断清楚。

4. 管理不方便

大项目里到处都是 jar,一个 spring.factories 一旦散落在天南地北的 jar 包里,谁还记得谁注册了啥?查配置都得翻好几页,全靠记性。

5. 跟 GraalVM 天生不合

GraalVM 是个静态编译的选手,构建原生镜像的时候你不能“偷偷加载”,你得提前告诉它你要用啥,扫描啥,反射啥。而 spring.factories 这种“我启动了再告诉你我要啥”的操作,人家根本不给你面子。
所以啊,SpringBoot 一咬牙,决定砍了它,改走新的路子。

新秀登场:imports 文件机制

说再见的时候也是时候迎来新朋友了。SpringBoot 3.0 引入了一个替代方案:按扩展点分门别类放配置文件,不再用一个 spring.factories 统管天下。
比如自动配置类,你就写进这个文件里:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
一行一个全类名,清清爽爽,没有键值对。
原来这么写:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.FooAutoConfiguration,\
com.example.BarAutoConfiguration
现在这么写:
com.example.FooAutoConfiguration
com.example.BarAutoConfiguration
是不是像极了把旧版 Excel 换成新版的 CSV 文件,清爽多了。
图片

新机制到底香在哪儿?

1. 性能提升了
只读你该读的,不再满世界翻 jar 包。启动速度自然就起来了。
2. 更好支持模块化
每种扩展点都有自己的“名单”,你想加啥自己列清楚,模块之间更独立,互不打扰。
3. 易读易写
没有 key=value 形式,一行一个类名,强迫症表示满意。
4. 更适合 AOT 和 GraalVM
这个才是关键点。imports 文件是静态的,构建时就能解析清楚,GraalVM 编译原生镜像的时候可以舒舒服服地知道你要加载哪些类,不用猜。

项目迁移怎么搞?

也不难,几步走完事儿:

步骤1:把自动配置类挪地方

原来是写在 spring.factories 里,现在把它写到:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
就完了。

步骤2:别的扩展点也分文件写

ApplicationListener 这些别的扩展点,也可以用类似方法或者直接用 Spring 注解配置,比如 @Bean 或者 @Component。

步骤3:自己写扩展点?照着 Spring 的做

如果你非得自定义扩展加载器,也可以模仿 Spring 的 SpringFactoriesLoader 新版写法,支持加载 imports 文件,不是难事。

Image

那以前的 spring.factories 还能用不?

还能用,但不推荐新项目继续用了,属于“临时兼容”。Spring 团队表示会慢慢淡出,不一定哪天就彻底停了,早点迁移安心。

总结一下

简单说,SpringBoot 3.0 取消 spring.factories 是一次“减负瘦身”,核心目标是为 GraalVM 原生镜像 打基础,让启动更快、结构更清晰,也更好地适配现代 Java 模块化和构建流程。
用上 imports 后,配置一目了然,性能更稳,还不用担心镜像构建失败。你要是搞微服务、搞 Serverless、搞容器,推荐早点适应这个变化。
毕竟,谁不想自己的服务像打车 App 一样秒起,资源还不费钱呢?再说,SpringBoot 都这么安排了,我们程序员也只能配合地笑着把代码再改一遍。

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

也可以看我写的这篇文章《DeepSeek满血复活,直接起飞!》来进行本地搭建。

-END-

ok,今天先说到这,老规矩,给大家分享一份不错的副业资料,感兴趣的同学可以链接我,微信:hls404 找我领取。

以上,就是今天的分享了,看完文章记得右下角点赞,也欢迎在评论区写下你的留言。