【问题标题】:Override bean definition doesn't work as expected覆盖 bean 定义没有按预期工作
【发布时间】:2015-10-07 05:38:53
【问题描述】:

我对 Spring 的基于注解的配置感到困惑。

我有一个接口 MyInterface 和两个实现这个接口的类(MyClass1 和 MyClass2)。

@Component("MyInterface")
public class MyClass1 implements MyInterface {

    public void execute() {
        System.out.println("MyClass1 executed");
    }
}

public class MyClass2 implements MyInterface {

    public void execute() {
        System.out.println("MyClass2 executed");
    }
}

MyClass1 是使用 Component-Scan 创建的,MyClass2 被定义为一个 bean:

@Configuration
@ComponentScan(basePackageClasses = MyClass1Configuration.class)
public class MyClass1Configuration {

}

@Configuration
public class MyClass2Configuration {

    @Bean(name = "MyInterface")
    public MyInterface myClass2() {
        return new MyClass2();
    }
}

我使用 Spring Test 的 ContextConfiguration 注解构建应用程序上下文:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyClass1Configuration.class, MyClass2Configuration.class})
public class SpringTestCase1 {

    @Autowired
    private MyInterface myInterface;

    @Test
    public void testMethod() {
        System.out.println("testMethod invoked");
        Assert.assertEquals(MyClass2.class, myInterface.getClass());
        myInterface.execute();
    }
}

不幸的是,测试失败了,因为 Class1 是自动装配的,而不是 Class2。预期的行为是 MyClass2Configuration 覆盖由 MyClass1Configuration 定义的 bean。我有什么错。

我在 GitHub 上创建了这个示例,如果您想查看一个工作示例: https://github.com/OLibutzki/spring-test-configuration/tree/master/simple-sprint-test

感谢您的帮助。

亲切的问候 奥利弗

【问题讨论】:

    标签: spring spring-bean


    【解决方案1】:

    或者您可以通过使用覆盖

    spring.main.allow-bean-definition-overriding=true

    在 main/resource/application.properties 中

    但它容易出错

    【讨论】:

    • “但它容易出错” - 你是说 Spring 对spring.main.allow-bean-definition-overriding 的处理容易出错吗?
    【解决方案2】:

    你已经很接近了……首先,你不能在同一个 Spring 上下文中拥有 2 个同名的 bean,除非你特别允许它,我不建议这样做,因为它容易出错。

    除此之外,您应该使用@Primary annotation,它可以在方法和类型级别应用。在您的情况下,您应该在 MyClass2Configuration 的方法级别应用它:

    @Configuration
    public class MyClass2Configuration {
    
        @Bean
        @Primary
        public MyInterface myClass2() {
            return new MyClass2();
        }
    }
    

    由于您是按类型(而不是按名称)自动装配,因此专门允许覆盖 bean 定义似乎没有用。您可以让两个 bean 都存在于 Spring 上下文中,然后通过 @Primary 注释,Spring 将自动装配您的“主要”bean 实例。

    【讨论】:

    • 谢谢,@Primary 是缺失的部分。
    【解决方案3】:

    一些春季版本有问题,我尝试将版本从 2.1.3 更改为 2.0.2.RELEASE。它开始工作了

    【讨论】:

      猜你喜欢
      • 2018-07-17
      • 1970-01-01
      • 2017-04-18
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多