配置动态刷新RefreshScope注解使⽤局限性(⼀)
在 Spring Cloud 体系的项⽬中,配置中⼼主要⽤于提供分布式的配置管理,其中有⼀个重要的注解:@RefreshScope,如果代码中需要动态刷新配置,在需要的类上加上该注解就⾏。本⽂分享⼀下笔者遇到与 @ConditionalOnSingleCandidate 注解冲突的问题
问题背景
项⽬再引⼊ RabbitMQ,在⾃定义 connectionFactory 时,⼿滑加上了 @RefreshScope
@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;
}
系统报错⽆法注⼊ RabbitTemplate
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'fresh.bug.RefreshBugApplicationTest':
Unsatisfied dependency expressed through field 'rabbitTemplate'; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException:
No qualifying bean of type 'org.springframework.RabbitTemplate' available: expected at least 1 bean which qualifies as autowire candidate.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
排查
1. 默认情况下 spring-boot-starter-amqp 会默认给我们注⼊ rabbitTemplate 实现
RabbitAutoConfiguration#rabbitTemplate
@Bean
@ConditionalOnSingleCandidate(ConnectionFactory.class)
@ConditionalOnMissingBean(RabbitOperations.class)
public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
RabbitTemplate template = new RabbitTemplate();
return template;
}
2. 开启 Spring Boot 启动 debugger ⽇志,查看注⼊信息
RabbitAutoConfiguration.RabbitTemplateConfiguration#rabbitTemplate:
Did not match:
- @ConditionalOnSingleCandidate (types: org.springframework.tion.ConnectionFactory; SearchStrategy: all)
did not find a primary bean from beans 'connectionFactory', 'tionFactory' (OnBeanCondition)
提⽰ConditionalOnSingleCandidate注解的⽅法不能查到唯⼀ConnectionFactory实现
3. 使⽤ @RefreshScope 注解的 bean,默认情况下同时会⽣成scopedTarget.beanName的 bean
@Autowired
private ApplicationContext context;
@Test
spring framework是什么系统
public void testRabbitTemplate() {
String[] beanNames = BeanNamesForType(ConnectionFactory.class);
for (String beanName : beanNames) {
System.out.println(beanName);
}
Assert.isTrue(beanNames.length == 2);
}
connectionFactory
4. 由于 ConditionalOnSingleCandidate 成⽴的条件是全局只能有⼀个此类型的 bean 所以默认的 RabbitTemplate ⽆法注⼊
常见被 ConditionalOnSingleCandidate 注解的 bean
1. 使⽤ JdbcTemplate ⽆法在⾃定义 DataSource 添加 @RefreshScope
@ConditionalOnSingleCandidate(DataSource.class)
public class JdbcTemplateAutoConfiguration {}
2. MailSenderValidator 邮件发送校验器⽆法添加 @RefreshScope
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(MailSenderAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.mail", value = "test-connection")
@ConditionalOnSingleCandidate(JavaMailSenderImpl.class)
public class MailSenderValidatorAutoConfiguration {}
3. 由于默认情况下涉及的 bean 很多,所以使⽤ RefreshScope 时⼀定要避免这些 bean
项⽬推荐:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。