覆盖 bean 定义不能按预期工作
Override bean definition doesn't work as expected
我对 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 测试的 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 上下文中有 2 个同名的 bean,除非你特别允许,我不推荐这样做,因为它是容易出错。
除此之外,您应该使用 @Primary
annotation,它可以在方法和类型级别应用。在您的情况下,您应该在 MyClass2Configuration
:
中的方法级别应用它
@Configuration
public class MyClass2Configuration {
@Bean
@Primary
public MyInterface myClass2() {
return new MyClass2();
}
}
由于您是按类型(而不是按名称)自动装配的,因此专门允许覆盖 bean 定义似乎没有用。您可以让两个 bean 都位于 Spring 上下文中,然后,通过 @Primary
注释,Spring 将自动装配您的 "primary" bean 实例。
或者您可以使用
覆盖它
spring.main.allow-bean-definition-overriding=true
在main/resource/application.properties
但它容易出错
某些 spring 版本有问题,我尝试将版本从 2.1.3 更改为 2.0。2.RELEASE。它开始工作
我对 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 测试的 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 上下文中有 2 个同名的 bean,除非你特别允许,我不推荐这样做,因为它是容易出错。
除此之外,您应该使用 @Primary
annotation,它可以在方法和类型级别应用。在您的情况下,您应该在 MyClass2Configuration
:
@Configuration
public class MyClass2Configuration {
@Bean
@Primary
public MyInterface myClass2() {
return new MyClass2();
}
}
由于您是按类型(而不是按名称)自动装配的,因此专门允许覆盖 bean 定义似乎没有用。您可以让两个 bean 都位于 Spring 上下文中,然后,通过 @Primary
注释,Spring 将自动装配您的 "primary" bean 实例。
或者您可以使用
覆盖它spring.main.allow-bean-definition-overriding=true
在main/resource/application.properties
但它容易出错
某些 spring 版本有问题,我尝试将版本从 2.1.3 更改为 2.0。2.RELEASE。它开始工作