带有父子关系的注释的Spring Bean覆盖

时间:2019-11-13 15:20:08

标签: java spring

我有两个具有父子关系的类,第二个是第一个的模拟。

public class A {
   public void doSomething(){...};
}

public class MockA extends A {
   @Override
   public void doSomething() {...};
}

我还有两个@Configuration类,一个用于开发环境,一个用于测试,测试一个仅模拟了几种行为,但它导入了开发中的一个。无论哪种方式,我都希望在测试环境中为MockA注入代码,并在开发中为A类注入其他将其自动连接的服务。

如果我在测试配置中覆盖Bean,我可以这样做。以下将起作用:

@Configuration
public class ApplicationConfig {
@Bean
    public A beanA() {
        return new A();
    }
}

@Configuration
public class TestApplicationConfig {
@Bean
    public A beanA() {
        return new MockA();
    }
}

但是,我不想在@Configuration类中创建bean。我想在每个组件上放置@Component批注,然后将它们正确注入服务中。

我尝试了两种方法

1)创建一个虚拟注释,将注释添加到类A上,并尝试从TestApplicationConfig中排除该bean。

@Configuration
@ComponentScan(
basePackages = {
        "murex.connectivity.tools.interfaces.monitor.cellcomputer",
        "murex.connectivity.tools.interfaces.monitor"
     }, excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = 
     MyAnnotation.class))
public class TestApplicationConfig {
}

2)在MockA类上使用@Component和@Primary批注。我的逻辑是,在两种情况都存在的情况下(这只会在测试用例中发生,因为只有在扫描MockA之后才会发生这种情况),MockA会被注入到所有地方。但这不会发生。

我想知道我是在做错什么,还是Spring的限制? @Primary批注似乎正是针对此特定情况构造的,我是否误解了?这两个类是否存在父子关系,这是事实吗?

L.E。使用两个不同的配置文件将起作用。如果我对所介绍的两种方法的理解是正确的,并且/或者如果这是对使用@Component注释的Spring的限制,我会感到好奇

2 个答案:

答案 0 :(得分:1)

您可以使用配置文件。

@Profile("!test")
@Configuration
public class ApplicationConfig {
    @Bean
    public A beanA() {
        return new A();
    }
}

对于测试用例: 在application.properties:spring.profiles.active=test或测试类@ActiveProfiles("test")的测试资源中,并创建配置:

@Profile("test")
@Configuration
public class TestApplicationConfig {
    @Bean
    public A beanA() {
        return new MockA();
    }
}

答案 1 :(得分:1)

试图结合两种建议的方法。它对我有用:

@Component
@Primary
public class ClassA {
    public void doSomething() {
        System.out.println("A");
    }
}

@Component
public class ClassB extends ClassA {
    @Override
    public void doSomething() {
        System.out.println("B");
    }
}

@Component
public class ClassC {
    @Autowired
    public ClassA component;
}

所有三个类都在同一包中。

@Configuration
@ComponentScan(value = "com.test", excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes =
        Primary.class))
public class RandomConfig {


}

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {RandomConfig.class})
public class RandomTest {

    @Autowired
    ClassC c;

    @Test
    void when_then() {
        //prints "B"
        c.component.doSomething();
    }

}

因此RandomConfig排除了所有@Primary bean,而生产配置仅使用@Primary