Spring 依赖注入:为何无法自动按名称匹配?
Spring 的依赖注入机制主要基于类型,而非名称。当遇到多个相同类型的 Bean 时(例如 TenantDataSource),它不会自动回退到按参数名称匹配。这是因为 Spring 无法始终保证方法中的参数名称与 Bean 名称匹配。
Java 默认情况下不会在编译后的字节码中保留参数名称。如果没有特殊配置,参数名称(例如 tenantADataSource 和 tenantBDataSource)会在编译期间被清除,并替换为通用的名称,如 arg0 和 arg1。 因此,Spring 无法得知 tenantADataSource 指的是名为 "tenantA-dataSource" 的 Bean。
解决参数名称保留问题
可以使用 -parameters
编译器标志来保留字节码中的参数名称:
<code>javac -parameters MyClass.java</code>
即使使用了此标志,Spring 仍然不会按参数名称匹配,除非明确配置。
Spring 避免做出假设以防止意外行为。例如,如果参数名称意外交换或命名错误,或者开发人员期望不同的映射,会发生什么? 如果没有明确的指导(例如 @Qualifier
),Spring 无法确定开发人员的意图,而选择抛出错误,而不是可能注入错误的 Bean。
Spring 遵循“显式优于隐式”的原则。依赖注入应该具有可预测性,并且不依赖于参数名称到 Bean 名称匹配之类的假设。Spring 的运作方式在不同的环境和框架中保持一致。某些语言或框架(如 Kotlin)默认保留参数名称,而其他语言则不保留,因此 Spring 避免依赖参数名称来实现关键功能。
何时名称匹配可以自动工作?
虽然 Spring 默认情况下不按参数名称匹配,但在某些情况下可以按参数名称匹配,但这取决于您的设置:
Spring 4.3 参数名称发现
如果使用 -parameters
标志编译代码,当存在歧义时,Spring 可以从参数名称推断 Bean 名称。
示例:
<code>@Autowired public TenantService(TenantDataSource tenantADataSource, TenantDataSource tenantBDataSource) { this.tenantADataSource = tenantADataSource; this.tenantBDataSource = tenantBDataSource; }</code>
如果使用了 -parameters
标志并且参数名称(tenantADataSource、tenantBDataSource)与 Bean 名称匹配,Spring 可以解决歧义。但是,这种行为在复杂的配置中并不总是可靠或可预测的,这就是为什么首选显式配置(例如 @Qualifier
)。
为什么 Spring 更倾向于使用 @Qualifier?
使用 @Qualifier
可以确保清晰度并消除歧义,使开发人员和框架都能明确意图。
示例:
<code>@Autowired public TenantService( @Qualifier("tenantA-dataSource") TenantDataSource tenantADataSource, @Qualifier("tenantB-dataSource") TenantDataSource tenantBDataSource ) { this.tenantADataSource = tenantADataSource; this.tenantBDataSource = tenantBDataSource; }</code>
这样,Spring 就能准确知道要注入哪些 Bean,而不管参数名称或其他因素如何。
Spring 应该更智能吗?
有人可能会认为像 Spring 这样的框架应该更智能,并在存在歧义时自动将 Bean 名称与参数名称匹配。但是:
- 向后兼容性: 自动更改此行为可能会破坏 Bean 名称和参数名称不匹配的现有应用程序。
-
可预测性: 显式地解决歧义(例如,通过
@Qualifier
)确保开发人员始终知道正在注入哪些 Bean。隐式假设可能会导致难以调试的问题,尤其是在大型复杂应用程序中。
真实场景中的情况
在大多数实际应用程序中:
- 开发人员使用有意义的 Bean 名称和参数名称,但他们也更喜欢像
@Qualifier
这样的显式配置以确保清晰度。 - 对于多实例场景,通常使用动态配置或基于工厂的方法(例如 AbstractRoutingDataSource),而不是手动连接各个 Bean。
关键要点
-
Spring 首先按类型注入: 如果只有一种类型的 Bean,Spring 会毫无问题地注入它。如果存在多种相同类型的 Bean,Spring 需要额外的提示(例如
@Qualifier
)来解决歧义。 -
参数名称不可靠: 默认情况下,参数名称不会保留在 Java 字节码中,因此 Spring 无法使用它们将 Bean 与参数匹配。即使保留了参数名称(
-parameters
),Spring 也会避免隐式基于名称的匹配,除非明确配置。 -
显式优于隐式: Spring 优先考虑可预测性,并鼓励开发人员使用显式配置(例如
@Qualifier
或@Primary
)而不是依赖于隐式匹配。 - Spring 的设计理念: 歧义错误可以防止意外行为,并确保开发人员完全控制依赖注入。
以上是春季 - 为什么要逐名 - 拟议中的标准的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Dreamweaver Mac版
视觉化网页开发工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

螳螂BT
Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

适用于 Eclipse 的 SAP NetWeaver 服务器适配器
将Eclipse与SAP NetWeaver应用服务器集成。

WebStorm Mac版
好用的JavaScript开发工具