Настройка ограничений использования аннотаций RefreshScope для динамического обновления (1)

Java

В проекте системы Spring Cloud центр конфигурации в основном используется для обеспечения распределенного управления конфигурацией.Есть важная аннотация: @RefreshScope.Если в коде требуется динамическое обновление конфигурации, просто добавьте эту аннотацию в нужный класс. В этой статье рассказывается о проблеме, связанной с конфликтами автора с аннотацией @ConditionalOnSingleCandidate.

фон проблемы

Проект представил RabbitMQ и добавил @RefreshScope при настройке connectionFactory.

@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, чтобы запустить журнал отладчика и просмотреть информацию об инъекциях.
   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, также генерируются по умолчанию.scopedTarget.beanNameБоб
@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

    1. Невозможно добавить @RefreshScope в пользовательский источник данных с помощью JdbcTemplate
@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-компонентов, обязательно избегайте этих bean-компонентов при использовании RefreshScope.

image