在 Spring Cloud 體系的項目中,配置中心主要用於提供分佈式的配置管理,其中有一個重要的註解:@RefreshScope,若是代碼中須要動態刷新配置,在須要的類上加上該註解就行。本文分享一下筆者遇到與 @ConditionalOnSingleCandidate 註解衝突的問題java
項目再引入 RabbitMQ,在自定義 connectionFactory 時,手滑加上了 @RefreshScopegit
@Bean
@RefreshScope
public CachingConnectionFactory connectionFactory() {
CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
connectionFactory.setAddresses("172.17.0.111");
connectionFactory.setUsername("guest");
connectionFactory.setPassword("guest");
connectionFactory.setVirtualHost("/");
return connectionFactory;
}複製代碼
系統報錯沒法注入 RabbitTemplategithub
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'com.pig4cloud.course.refresh.bug.RefreshBugApplicationTest':
Unsatisfied dependency expressed through field 'rabbitTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.amqp.rabbit.core.RabbitTemplate' available: expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
複製代碼
RabbitAutoConfiguration#rabbitTemplatespring
@Bean
@ConditionalOnSingleCandidate(ConnectionFactory.class)
@ConditionalOnMissingBean(RabbitOperations.class)
public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate();
configurer.configure(template, connectionFactory);
return template;
}複製代碼
RabbitAutoConfiguration.RabbitTemplateConfiguration#rabbitTemplate:
Did not match:
- @ConditionalOnSingleCandidate (types: org.springframework.amqp.rabbit.connection.ConnectionFactory; SearchStrategy: all)
did not find a primary bean from beans 'connectionFactory', 'scopedTarget.connectionFactory' (OnBeanCondition)複製代碼
提示 ConditionalOnSingleCandidate
註解的方法不能查找到惟一 ConnectionFactory
實現express
scopedTarget.beanName
的 bean@Autowired
private ApplicationContext context;
@Test
public void testRabbitTemplate() {
String[] beanNames = context.getBeanNamesForType(ConnectionFactory.class);
for (String beanName : beanNames) {
System.out.println(beanName);
}
Assert.isTrue(beanNames.length == 2);
}
scopedTarget.connectionFactory
connectionFactory複製代碼
@ConditionalOnSingleCandidate(DataSource.class)
public class JdbcTemplateAutoConfiguration {}複製代碼
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(MailSenderAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.mail", value = "test-connection")
@ConditionalOnSingleCandidate(JavaMailSenderImpl.class)
public class MailSenderValidatorAutoConfiguration {}複製代碼