Java SPI加载服务实例,Spring Factories加载配置类;前者被动触发、无生命周期管理,后者启动时批量加载并交由IOC容器统一管理。
java spi 和 spring factories 都解决“接口与实现分离+运行时动态加载”的问题,但它们的加载目标、时机、控制粒度和工程适配性差异显著。spi 加载的是服务实例(即实现了某个接口的对象),而 spring factories 加载的是配置类或处理器类(如 autoconfiguration、applicationcontextinitializer),这些类本身不直接提供业务功能,而是参与 spring 容器的构建流程。
加载对象类型不同:实例 vs 配置元数据
SPI 的 ServiceLoader 最终调用 newInstance() 创建具体实现类的实例,例如 JsonSerializer 或 JdbcDriver,这些对象可立即用于业务逻辑。它面向的是“能干活的服务”。
Spring Factories 则通过 SpringFactoriesLoader.loadFactoryNames() 读取类名列表,再由 Spring 容器按需决定是否实例化——可能作为 @Configuration 类被解析,也可能作为 @Bean 方法的宿主,甚至只是注册一个监听器。它面向的是“影响容器行为的扩展点”。
加载时机与生命周期管理差异
SPI 是被动触发式加载:只有显式调用 ServiceLoader.load(X.class) 才开始扫描、读取、反射创建;每个调用都可能产生新实例,无统一生命周期管理。
Spring Factories 是启动驱动式加载:在 Spring Boot 启动早期(如 SpringApplication.run() 第一步)就批量读取所有 META-INF/spring.factories,解析出类名并注册为候选配置,后续交由 IOC 容器统一管理——支持单例、懒加载、依赖注入、销毁回调等完整 Bean 生命周期。
条件控制能力悬殊
SPI 本身不支持条件逻辑:只要 jar 在 classpath,对应实现类就会被 ServiceLoader 扫描到并尝试实例化,哪怕当前环境根本用不上(比如 H2 驱动在生产 MySQL 环境中仍会被加载)。
Spring Factories 天然集成 Spring 条件机制:@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty 等注解可嵌套在自动配置类内部,让整个配置块按需激活。这使得 Spring Boot 能做到“引入即生效,不引入不干扰”。
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
配置组织方式影响可维护性
SPI 要求每个接口单独一个文件(META-INF/services/com.example.Serializer),多接口多文件,分散且易遗漏。
Spring Factories 把所有扩展点收敛到单个文件(META-INF/spring.factories),用键值对形式组织:
立即学习“Java免费学习笔记(深入)”;
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.MyAutoConfiguration,\ com.example.OtherAutoConfiguration这种结构更利于模块归类、版本对齐和 IDE 支持,也方便框架做统一排序(如 @Order)、过滤和覆盖。

















