@RefreshScope в классе конфигурации - PullRequest
0 голосов
/ 01 июля 2019

У меня есть приложение весенней загрузки. Я использую Spring Cloud Config для вывода свойств через Git. Все отлично работает Я хотел бы, чтобы компоненты обновлялись при выдаче конечной точки обновления привода. Фасоль обновляется, как и ожидалось, выполняя следующие действия:

@EventListener
public void onRefreshScopeRefreshed(final RefreshScopeRefreshedEvent event) {
    logger.info("Received Refresh event. Refreshing all beans...");
    for (String beanName : applicationContext.getBeanDefinitionNames()) {
        Class<?> beanClass = applicationContext.getBean(beanName).getClass();
        if(beanClass.getName().contains("SpringCGLIB")) {
            logger.info("Proxied bean: bean name: " + beanName + " - Bean class: " + applicationContext.getBean(beanName).getClass());
        } else {
            logger.info("Regular Bean: Bean name: " + beanName + " - Bean class: " + applicationContext.getBean(beanName).getClass());
        }
        applicationContext.getBean(beanName).getClass(); // to cause refresh eagerly
    }
}

Единственное, что не работает должным образом, это когда я аннотирую класс Configuration с помощью @refreshScope (имеется в виду на уровне класса), бины, объявленные в этом классе, не обновляются, если они не имеют @RefreshScope в объявлении bean-компонента.

Здесь боб не обновляется:

@Configuration
@RefreshScope
public class DraftsClientConfiguration {

    @Bean
    MyBean aBean() {
        return new MyBean();
    }
}

Вот журнал из моего класса RefreshListener: Мы видим, что в этом случае есть только один компонент, который не проксирован.

RefreshListener - Regular Bean: Bean name: draftsServiceClient - Bean class: class com.citi.qi.athena.drafts.DraftsServiceClient

Но здесь бин обновляется:

@Configuration
public class DraftsClientConfiguration {

    @RefreshScope
    @Bean
    MyBean aBean() {
        return new MyBean();
    }
}

Во втором случае у нас есть два bean-компонента (должно быть, так), один с прокси и один без прокси.

RefreshListener - Regular Bean: Bean name: scopedTarget.draftsServiceClient - Bean class: class com.citi.qi.athena.drafts.DraftsServiceClient
RefreshListener - Proxied bean: bean name: draftsServiceClient - Bean class: class com.citi.qi.athena.drafts.DraftsServiceClient$$EnhancerBySpringCGLIB$$bbfd1caf

Я проверяю, обновлен компонент или нет, помещая точку останова в объявление компонента.

Согласно Spring doc, bean-компоненты должны обновляться аннотированием @RefreshScope на уровне класса конфигурации. Нет необходимости указывать @RefreshScope для каждого объявления бина класса конфигурации. Я что-то упустил?

Между прочим, я проверяю, обновлен ли компонент или нет, помещая точку останова в объявление компонента.

Второй вопрос: я думаю, у меня должен быть только один прокси-компонент, а не два, как мы видим во втором случае?

1 Ответ

2 голосов
/ 01 июля 2019

Ваше понимание немного не в порядке, и все это указано в документации.

Из Javadoc из @RefreshScope.

Реализация предполагает создание прокси для каждого компонента в области действия,

Таким образом, вы получите 2 экземпляра боба. 1 прокси, который фактически обернет полный экземпляр компонента. При обновлении прокси-сервер будет работать, а фактический экземпляр будет заменен.

Из Справочного руководства Spring Cloud :

@RefreshScope работает (технически) на классе @Configuration, но это может привести к неожиданному поведению. Например, это не означает, что все @Bean, определенные в этом классе, сами находятся в @RefreshScope. В частности, все, что зависит от этих компонентов, не может полагаться на то, что они обновляются при запуске обновления, если только оно не находится в @RefreshScope. В этом случае он перестраивается при обновлении, а его зависимости повторно вводятся. В этот момент они повторно инициализируются из обновленного @Configuration).

Таким образом, хотя технически возможно использование ссылок на эти компоненты не может обновляться, если только они не помечены как @RefreshScope.

Короче говоря, решение состоит в том, чтобы явно пометить, какие компоненты должны быть в @RefreshScope, либо аннотируя класс как @RefreshScope, либо как метод @Bean.

...