在 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. HTTP2 的前世今生

    本文转载自HTTP2 的前世今生 导语 作为一名 Web 后端开发工程师,无论是工作中,还是面试时,对于 HTTP 协议的理解都是必不可少的.而 HTTP2 协议的发布更是解决了 HTTP1.1 协议 ...

  2. Java开发工程师最新面试题库系列——Spring部分(附答案)

    Spring Spring框架是什么? 答:Spring是轻量级的面向切面和控制反转的框架.初代版本为2002年发布的interface21,Spring框架是为了解决企业级应用开发的复杂性的出现的, ...

  3. java实现压缩文件

    原文链接:https://www.cnblogs.com/zeng1994/p/7862288.html

  4. Django框架-cookie和session以及中间件

    目录 一.cookie 和 session 1.为什么会有这些技术 2. cookie 2.1 Django如何设置cookie 2.2 Django如何获取cookie 2.3 Django如何设置 ...

  5. 剑指 Offer 63. 股票的最大利润 + 动态规划

    剑指 Offer 63. 股票的最大利润 Offer_63 题目描述 方法一:暴力法 package com.walegarrett.offer; /** * @Author WaleGarrett ...

  6. Java的特性和优势以及不同版本的分类,jdk,jre,jvm的联系与区别,javadoc的生成

    Java 1.Java的特性和优势 Write Once,Run Anywhere 简单性 面向对象 可移植性 高性能 分布式 动态性 多线程 安全性 健壮性 2.Java的三大版本 JavaSE:标 ...

  7. 翻译:《实用的Python编程》03_06_Design_discussion

    目录 | 上一节 (3.5 主模块) | 下一节 (4 类) 3.6 设计讨论 本节,我们重新考虑之前所做的设计决策. 文件名与可迭代对象 考虑以下两个返回相同输出的程序. # Provide a f ...

  8. Pyqt5学习笔记(一)

    Python已有的GUI框架: Tkinter(python内嵌的GUI环境,使用TCL实现,易学易用,方便简单创GUI自带无需安装,适用于Unix.Windows和Mac系统组,在Tk8.0的后续版 ...

  9. Python:垃圾回收

    有很多不同的方法来实现垃圾回收,例如跟踪,引用计数,转义分析,时间戳和心跳信号等.不同的语言依赖于不同的垃圾回收实现,例如,有些将其与编译器和运行时系统集成在一起.而其他语言则可能需要事后设置,甚至可 ...

  10. 策略模式在PHP业务代码的实践

    [大话设计模式]-- 策略者模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变法,不会影响到使用算法的客户. 策略模式的核心就是屏蔽内部策略算法,内部的 ...