provides 不适用于 Spring 服务注入,因其属于 Java 模块系统,仅影响 ServiceLoader 加载机制,与 Spring IoC 容器无关;Spring 依赖注入由自身容器控制,不解析 module-info.java 中的 provides 声明。

Spring 框架本身不支持 provides 语法——该关键字属于 Java 9+ 的模块系统(JPMS),用于 module-info.java 中声明“本模块向其他模块提供哪些服务实现”,它不参与 Spring 的 Bean 管理或运行时依赖注入。因此,**不能用 provides 实现 Spring 中多实现类的服务注入或策略选择**。
为什么 provides 不适用于 Spring 的服务注入?
provides 是模块层的编译/加载期声明,仅影响 JVM 类加载器如何解析 ServiceLoader.load() 所需的服务实现,与 Spring 容器无关。它面向的是 java.util.ServiceLoader 机制,而非 @Autowired 或 @Resource。Spring 的依赖注入完全由自身 IoC 容器控制,不读取 module-info.java 中的 provides 声明。
真正可行的 Spring 多实现注入方案
以下是在 Spring Boot 中管理多个实现类并按需选择的核心方式,已验证可用于生产环境:
- @Qualifier + 自定义 Bean 名:为每个实现类指定唯一 Bean 名,注入时显式指定
-
@Primary:标记默认实现,避免无注解注入失败;非默认场景仍需
@Qualifier - Map<String, X> 注入:Spring 自动将所有 X 类型 Bean 收集为 Map,key 为 Bean 名,适合策略工厂模式
-
@Profile + 环境隔离:用
@Profile("beijing")/@Profile("shanghai")控制不同环境启用对应实现
策略变量选择的推荐实战结构
以地区差异化业务为例,构建可扩展、易维护的策略选择体系:
- 定义统一接口:
IDemoService - 两个实现类分别标注
@Service("demoServiceBeijing")和@Service("demoServiceShanghai") - 编写策略工厂类,注入
Map<String, IDemoService>,通过参数(如请求头、配置项、URL 路径)动态获取对应实例 - 在 Controller 中调用工厂方法,传入策略标识(如
"beijing"),避免硬编码或 if-else 分支
注意边界:ServiceLoader 与 Spring 可共存但不自动集成
若你确实使用了 provides 配合 ServiceLoader(例如在模块中声明 provides IDemoService with DemoServiceBeijing;),它只能被 ServiceLoader.load(IDemoService.class) 加载,不会注册为 Spring Bean。如需纳入 Spring 管理,必须手动用 @Bean 方法包装并注册,例如:
@Bean<br>@ConditionalOnMissingBean<br>public IDemoService demoServiceFromServiceLoader() {<br> return ServiceLoader.load(IDemoService.class)<br> .findFirst().orElseThrow(() -> new IllegalStateException("No service found"));<br>}

















