Spring,基于注释,覆盖组件

时间:2017-04-27 15:57:31

标签: java spring

当我使用XML设置Spring时,可以覆盖稍后加载的XML文件中的组件定义。 它对测试非常有用 - 我创建默认配置集,然后使用添加测试配置加载它,用一些特殊的(存根,模拟等)替换一些组件。 现在我开始迁移到基于注释的配置,这会导致一些问题。

使用注释的直接方法是使用@Component

自动发现包

所以我有

@Configuration
@ComponentScan({"some.pack1", "some.pack2"})
public class ProductConfig{}

何时     @组态     @Import({ProductConfig.class})     @ComponentScan({" test.pack"})     公共类TestConfig {}

但如果我尝试覆盖test.pack中的组件

,则会导致冲突

我能做什么?

经过一些调查,其中有3个答案,其中有一些问题

  1. 最糟糕 - 我可以在ComponentScan上使用@Filter - 这是最糟糕的方式,
    • 我不能导入现有的配置(可以有一些额外的bean)
    • 我必须重新扫描所有组件,并明确定义一组过滤器
  2. 我可以使用@Profile和activeProfiles - 它更好,虽然它更复杂,但是,但是
    • 这意味着我必须在产品类中知道在某些测试中可以禁用它们
  3. 不要在覆盖Config时使用@ComponentScan并使用@Bean
    • 它可能在测试配置上很好,但这意味着我失去了使用@Component注释的能力
  4. 在上下文中使用setParent - 它运行良好,但是
    • 它不是在接口
    • 上实现ApplicationContext的显式操作
    • 如果覆盖服务对来自覆盖配置的某些组件具有@Autwire依赖性,则不难设置 - 需要手动注册并刷新
  5. 覆盖配置的最佳和标准方法是什么?当我使用基于XML的时候,这不是一个问题......

1 个答案:

答案 0 :(得分:1)

@profile在实施服务/代码的测试策略时起着至关重要的作用。

例如,在开发过程中,您可能有:

public interface DataSource{
 public String getHost();
}

默认实施

@Component
@Profile("Prod") 
public class DevDataSource implements DataSource {
    public String getHost(){
     // return actual value
}

组件测试的实现(假冒)

@Component
@Profile("test") 
public class StubbyDataSource implements DataSource {
    public String getHost(){
     return "some-host";   // return mocked data
}

现在你可以在这里编写一个测试,它可以作为集成测试单元测试组件测试https://martinfowler.com/bliki/ComponentTest.html

通过这种方式,您的测试策略将更加优雅,简洁且易于维护。 只需更改配置文件,相同的测试就可以指向不同的环境(真实或虚假)。