在 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 '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)}

排查

    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();
configurer.configure(template, connectionFactory);
return template;
}
    1. 开启 Spring Boot 启动 debugger 日志,查看注入信息
   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 实现

    1. 使用 @RefreshScope 注解的 bean,默认情况下同时会生成 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
    1. 由于 ConditionalOnSingleCandidate 成立的条件是全局只能有一个此类型的 bean 所以 默认的 RabbitTemplate 无法注入

常见被 ConditionalOnSingleCandidate 注解的 bean

    1. 使用 JdbcTemplate 无法在自定义 DataSource 添加 @RefreshScope
@ConditionalOnSingleCandidate(DataSource.class)
public class JdbcTemplateAutoConfiguration {}
    1. MailSenderValidator 邮件发送校验器无法添加 @RefreshScope
@Configuration(proxyBeanMethods = false)
@AutoConfigureAfter(MailSenderAutoConfiguration.class)
@ConditionalOnProperty(prefix = "spring.mail", value = "test-connection")
@ConditionalOnSingleCandidate(JavaMailSenderImpl.class)
public class MailSenderValidatorAutoConfiguration {}
    1. 由于默认情况下涉及的 bean 很多,所以使用 RefreshScope 时一定要避免这些 bean

项目推荐: Spring Cloud 、Spring Security OAuth2的RBAC权限管理系统 欢迎关注

配置动态刷新RefreshScope注解使用局限性(一)的更多相关文章

  1. SpringCloud04 服务配置中心、消息总线、远程配置动态刷新

    1 环境说明 JDK:1.8 MAVENT:3.5 SpringBoot:2.0.5.RELEASE SpringCloud:Finchley.SR1 2 创建服务注册中心(Eureka服务端) 说明 ...

  2. spring boot 配置动态刷新

    本文测试使用的spring cloud版本为: Dalston.SR1 很多朋友只知道spring cloud config可以刷新远程git的配置到内存中, 却不知道spring cloud con ...

  3. spring,mybatis事务管理配置与@Transactional注解使用[转]

    spring,mybatis事务管理配置与@Transactional注解使用[转] spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是至关 ...

  4. spring的配置模式与注解模式基础

    “依赖注入”是spring的核心特征,在Web服务器(如Tomcat)加载时,它会根据Spring的配置文件中配置的bean或者是通过注解模式而扫描并装载的bean实例自动注入到Application ...

  5. 关于什么是SpringMVC,和SpringMVC基于xml配置、注解配置、纯注解配置

    首先我们先要了解一下,什么是SpringMVC? SpringMVC是Spring框架内置的MVC的实现.SpringMVC就是一个Spring内置的MVC子框架,也就是说SpringMVC的相关包都 ...

  6. 事务管理配置与@Transactional注解使用

    spring,mybatis事务管理配置与@Transactional注解使用 概述 事务管理对于企业应用来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性. Spring Framewor ...

  7. spring,mybatis事务管理配置与@Transactional注解使用

    spring,mybatis事务管理配置与@Transactional注解使用[转]   spring,mybatis事务管理配置与@Transactional注解使用 概述事务管理对于企业应用来说是 ...

  8. spring启动,spring mvc ,要不要xml配置,基于注解配置

    老项目是09-11年搞的,用的是spring+struts2,没有用注解,全xml配置.web.xml中也配置了一大堆. 现在启动新项目,在项目中用spring+springmvc ,主要用注解,也用 ...

  9. springmvc-02(配置版与注解版区别)

    首先,我们来看配置版和注解版的相同步骤: 1.新建一个Moudle , springmvc-02-hello , 添加web的支持! 2.确定导入了SpringMVC 的依赖! 3.配置web.xml ...

随机推荐

  1. 人物传记——Kyle Tedford:持之以恒的品质从哪里来?

    心理学家表示,95%的人类行为发生在无意识中,而大多数这种行为是由习惯引起的.习惯,就像我们大脑设定的程序.通过每日持续努力,你会把坚持的习惯节奏慢慢进入身体中,并且会很容易加持下去. 做事三分钟热度 ...

  2. gitLab的使用 和 git 、 github、gitlab的区别

    一.git . github.gitlab的区别  (百度相关内容得到的理解) ​ ​ 二.git最基本作用:版本控制 ​ 三.有集成了git的GIT安装包 github和gitlab都使用git该版 ...

  3. Fast-RTPS简介

    RTPS即DDS中的主要核心通信部分.它提供实时高效的去中心化publish/subscribe通信机制.是ROS-2的核心底层通信组件,也是未来机器人/无人驾驶领域一个必然的方向. 资料参考: ht ...

  4. 手把手教你Centos7 部署 gitlab社区版

    一.前置说明: 操作系统:Centos 7 物理内存:>=2G 本人亲测,如果安装低版本的gitlab,比如我这里所使用的v8.17.0,物理内存1G,swap 2G虚拟内存即可部署.高版本的所 ...

  5. servlet内置对象(传递数据)

    一个servlet向另一个servlet发送数据,可以将数据放置在一个容器中(io.数据库.servlet的内置对象),servlet的内置对象成本最小. 一共有三个内置对象. 名字 类型 reque ...

  6. GPU 总结

    What features of GPUs allow them to perform computations faster than a typical CPU? GPUs have a mass ...

  7. elasticsearch如何设计集群

    本文为博客园作者所写: 一寸HUI,个人博客地址:https://www.cnblogs.com/zsql/ 在写本文时就在想,如果让你负责一个elasticsearch集群,从零开始,你会从哪些方面 ...

  8. MySQL注入点与SQL语句的关系

    目录 注入位置分类 内联式 - UNION query SQL injection 终止式 - End SQL injection 堆叠式 - Stacked queries SQL injectio ...

  9. AOP面试造火箭始末

    本文已整理致我的github地址,欢迎大家 star 支持一下 这是一个困扰我司由来已久的难题,Dubbo 了解过吧,对外提供的服务可能有多个方法,一般我们为了不给调用方埋坑,会在每个方法里把所有异常 ...

  10. C#中的字段与属性的区别及属性的作用

    C#中的字段与属性的区别及属性的作用 先上代码 public class Employee { //字段 private string name; //属性 public string Name { ...