【问题标题】:How to overwrite Spring service beans by name, using annotations only如何按名称覆盖 Spring 服务 bean,仅使用注释
【发布时间】: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 类。

【问题讨论】:

    标签: spring javabeans overwrite autowired inject


    【解决方案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 并不会太痛苦,因为只使用注解更诱人。
      猜你喜欢
      • 2012-08-03
      • 2017-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-03
      • 2020-06-02
      • 2017-02-18
      相关资源
      最近更新 更多