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 默认情况下不按参数名称匹配,但在某些情况下可以按参数名称匹配,但这取决于您的设置:
如果使用 -parameters
标志编译代码,当存在歧义时,Spring 可以从参数名称推断 Bean 名称。
<code>@Autowired public TenantService(TenantDataSource tenantADataSource, TenantDataSource tenantBDataSource) { this.tenantADataSource = tenantADataSource; this.tenantBDataSource = tenantBDataSource; }</code>
如果使用了 -parameters
标志并且参数名称(tenantADataSource、tenantBDataSource)与 Bean 名称匹配,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 这样的框架应该更智能,并在存在歧义时自动将 Bean 名称与参数名称匹配。但是:
@Qualifier
)确保开发人员始终知道正在注入哪些 Bean。隐式假设可能会导致难以调试的问题,尤其是在大型复杂应用程序中。在大多数实际应用程序中:
@Qualifier
这样的显式配置以确保清晰度。@Qualifier
)来解决歧义。-parameters
),Spring 也会避免隐式基于名称的匹配,除非明确配置。@Qualifier
或 @Primary
)而不是依赖于隐式匹配。以上是春季 - 为什么要逐名 - 拟议中的标准的详细内容。更多信息请关注PHP中文网其他相关文章!