Spring 用非主 bean 覆盖主 bean
Spring overriding primary bean with non-primary bean
我试图在使用@Primary 在测试配置中声明的测试期间覆盖 Spring bean。一个声明在 src/main/java 路径中,另一个主要声明在 src/test/java 路径中。
但是,Spring 故意用非主 bean 替换主 bean,我不想将其用于测试。如果我简单地注释掉生产 (src/main/java) 配置 bean,它会根据需要在测试配置中使用主要测试 (src/main/test) bean。 (很明显,我不能每次想 运行 测试时都注释掉代码。)
来自日志:
o.s.b.f.s.DefaultListableBeanFactory - Overriding bean definition for bean 'sqsConnectionFactory' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=testJmsConfiguration; factoryMethodName=sqsConnectionFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/foo/configuration/TestJmsConfiguration.class]]
with
[Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jmsConfiguration; factoryMethodName=sqsConnectionFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/foo/configuration/JmsConfiguration.class]]
为什么 spring 将主 bean 替换为非主 bean,我如何才能 Spring 使用特别标记为主 bean 的 bean?
编辑:
src/main/java配置:
@Configuration
public class JmsConfiguration {
... other bean declarations here ...
@Bean
public SQSConnectionFactory sqsConnectionFactory(Region region) throws JMSException {
return SQSConnectionFactory.builder()
.withRegion(region)
.build();
}
}
测试配置:
@Configuration
public class TestJmsConfiguration {
@Bean(name="messageProducerMock")
public MessageProducer mockMessageProducer() {
return new MessageProducerMock();
}
... other bean declarations here ...
@Bean
@Primary
public SQSConnectionFactory sqsConnectionFactory(@Qualifier("messageProducerMock") MessageProducer messageProducerMock) throws JMSException {
... returning setup mock here
}
}
带有测试的 class 注释为:
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles(profiles = {"test"})
我认为你可能在测试中遗漏了 @ContextConfiguration
class。
测试配置示例 class (src/test/java/TestConfiguration.class):
@Configuration
@ComponentScan
public class TestConfiguration {
@Bean
RabbitSender rabbitSender() {
return mock(RabbitSender.class);
}
}
测试示例class:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class SomeServiceTest {
}
@Primary
只在注入点生效,当不同的bean匹配注入的条件有冲突,需要做决定。
@Primary
未在 bean 初始化时使用。由于您使用两种不同的方法创建同一个 bean,并且您没有命名它们中的任何一个 Spring 认为您正在尝试覆盖它,因此可能会发生这种行为。给定名称是最简单的解决方案,但请记住,您的上下文仍将初始化您不想使用的 bean。
我试图在使用@Primary 在测试配置中声明的测试期间覆盖 Spring bean。一个声明在 src/main/java 路径中,另一个主要声明在 src/test/java 路径中。
但是,Spring 故意用非主 bean 替换主 bean,我不想将其用于测试。如果我简单地注释掉生产 (src/main/java) 配置 bean,它会根据需要在测试配置中使用主要测试 (src/main/test) bean。 (很明显,我不能每次想 运行 测试时都注释掉代码。)
来自日志:
o.s.b.f.s.DefaultListableBeanFactory - Overriding bean definition for bean 'sqsConnectionFactory' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=testJmsConfiguration; factoryMethodName=sqsConnectionFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/foo/configuration/TestJmsConfiguration.class]]
with
[Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=jmsConfiguration; factoryMethodName=sqsConnectionFactory; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/foo/configuration/JmsConfiguration.class]]
为什么 spring 将主 bean 替换为非主 bean,我如何才能 Spring 使用特别标记为主 bean 的 bean?
编辑: src/main/java配置:
@Configuration
public class JmsConfiguration {
... other bean declarations here ...
@Bean
public SQSConnectionFactory sqsConnectionFactory(Region region) throws JMSException {
return SQSConnectionFactory.builder()
.withRegion(region)
.build();
}
}
测试配置:
@Configuration
public class TestJmsConfiguration {
@Bean(name="messageProducerMock")
public MessageProducer mockMessageProducer() {
return new MessageProducerMock();
}
... other bean declarations here ...
@Bean
@Primary
public SQSConnectionFactory sqsConnectionFactory(@Qualifier("messageProducerMock") MessageProducer messageProducerMock) throws JMSException {
... returning setup mock here
}
}
带有测试的 class 注释为:
@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles(profiles = {"test"})
我认为你可能在测试中遗漏了 @ContextConfiguration
class。
测试配置示例 class (src/test/java/TestConfiguration.class):
@Configuration
@ComponentScan
public class TestConfiguration {
@Bean
RabbitSender rabbitSender() {
return mock(RabbitSender.class);
}
}
测试示例class:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class SomeServiceTest {
}
@Primary
只在注入点生效,当不同的bean匹配注入的条件有冲突,需要做决定。
@Primary
未在 bean 初始化时使用。由于您使用两种不同的方法创建同一个 bean,并且您没有命名它们中的任何一个 Spring 认为您正在尝试覆盖它,因此可能会发生这种行为。给定名称是最简单的解决方案,但请记住,您的上下文仍将初始化您不想使用的 bean。