如何按名称覆盖 Spring 服务 bean,仅使用注释

Posted

技术标签:

【中文标题】如何按名称覆盖 Spring 服务 bean,仅使用注释【英文标题】:How to overwrite Spring service beans by name, using annotations only 【发布时间】:2011-07-31 08:57:41 【问题描述】:

鉴于我将 Spring bean 配置为

@Service("myService")
public class DefaultService extends MyService 

还有一个使用这个 bean 的类

public class Consumer 
    @Autowired
    @Qualifier("myService")
    private MyService service;
    ...

我现在希望我的项目(包括前面的类)能够注入 Consumer 的另一个 MyService 实现。因此我想覆盖bean myService

@Service("myService")
public class SpecializedService implements MyService 

导致Consumer 现在携带SpecializedService 的实例而不是DefaultService。根据定义,我不能在 Spring 容器中拥有两个同名的 bean。我怎么能告诉春天,新服务的定义将覆盖旧服务?我不想修改Consumer 类。

【问题讨论】:

【参考方案1】:

我知道,已经晚了。还在发。

您应该为 MyService 的不同实现使用不同的名称。

例如

@Service("mySpecializedService")
public class SpecializedService implements MyService 


@Service("myService")
public class DefaultService extends MyService 
 

在自动装配它们时(比如在控制器中),您可以使用@Qualifier 注入所需的实现,如下所述。

获取默认实现

@Autowired
@Qualifier("myService")
MyService myService;   

获得专门的实现

@Autowired
@Qualifier("mySpecializedService")
MyService myService;

【讨论】:

这与 OP 的要求完全相反。 我会在一个单独的配置文件(xml 或 java)中定义新的 bean,并让它覆盖前一个,或者继续使用 Spring Profiles 或 @Conditional。 【参考方案2】:

基于注解的连接发生在基于 XML 的配置之前,这意味着在 XML 中定义的 bean 将 覆盖注释完成的那些接线。 所以在 XML 中明确定义它,就像 Willie 所说的那样会完成这项工作

<bean id="myService" class="x.y.z.SpecializedService" />

Spring 建议对服务和存储库 bean 使用 XML,对 MVC bean 使用注释。它还建议 @Autowired 不扫描组件。但是通常鼓励使用注释,尽管它将代码和配置合并在一起(反对分离关注点)。

第二件事是在它被传递的地方使用@Qualifiers("id of declared bean")。

【讨论】:

【参考方案3】:

使用过滤器将其从组件扫描中排除

<component-scan base-package="your-package">
    <exclude-filter type="regex" expression="DefaultService" />
</component-scan>

不确定是否有办法只使用注释(除了从 DefaultService 中删除 @Service 注释)。

【讨论】:

谢谢,Wilhelm,我相信您的解决方案会奏效。但随后我将不得不自己扫描我的服务。好主意!【参考方案4】:

要么明确定义服务 bean

<bean id="myService" class="x.y.z.SpecializedService" />

或组件扫描它。

在任何一种情况下,在您的应用程序上下文中,避免显式定义 DefaultService 并避免对其进行组件扫描。

【讨论】:

谢谢,威利。我们最终得到了您的解决方案,因为我们还出于维护原因(我们正在谈论数百个服务)决定将每个服务的列表保存在一个文件中 - 即 spring bean 配置。只定义 id 和 classname 并不会太痛苦,因为只使用注解更诱人。

以上是关于如何按名称覆盖 Spring 服务 bean,仅使用注释的主要内容,如果未能解决你的问题,请参考以下文章

Spring4-自动装配Beans-按属性名称自动装配

Spring Boot:在单元测试中用一个覆盖多个bean

Spring Boot - 不覆盖服务器端口属性

Spring自动装配Bean的五种方式

如何在不覆盖 Spring Boot 使用的情况下定义自定义 ObjectMapper bean

Spring4-自动装配Beans-按属性的数据类型自动装配Bean