zoukankan      html  css  js  c++  java
  • 配置动态刷新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 '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权限管理系统 欢迎关注

  • 相关阅读:
    Python-OpenCV——进阶操作一网打尽
    深入理解jQuery插件开发
    Bootstrap整合ASP.NET MVC验证、jquery.validate.unobtrusive
    实用的Bootstrap的扩展和插件集合
    hadoop编程小技巧(5)---自定义输入文件格式类InputFormat
    mapreduce作业状态一直是ACCEPTED
    hadoop CLASSNAME命令使用注意点
    运行java的class文件方法详解
    Hadoop、Zookeeper、Hbase分布式安装教程
    java enum(枚举)使用详解 + 总结
  • 原文地址:https://www.cnblogs.com/leng-leng/p/13254590.html
Copyright © 2011-2022 走看看