【发布时间】:2019-11-11 22:58:36
【问题描述】:
我有一个 Spring Boot 应用程序。我正在使用 Spring Cloud Config 来外部化属性 - 通过 Git。一切正常。 我希望在发出执行器刷新端点时刷新 bean。通过执行以下操作,Bean 会按预期急切地刷新:
@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
}
}
唯一没有按预期工作的是,当我使用 @refreshScope 注释配置类时(意味着在类级别),如果在此类中声明的 bean 在 bean 声明中没有自己的 @RefreshScope,则不会刷新它们。
这里的bean没有刷新:
@Configuration
@RefreshScope
public class DraftsClientConfiguration {
@Bean
MyBean aBean() {
return new MyBean();
}
}
这是我的 RefreshListener 类的日志: 我们可以看到,在这种情况下,只有一个 bean 没有被代理。
RefreshListener - Regular Bean: Bean name: draftsServiceClient - Bean class: class com.citi.qi.athena.drafts.DraftsServiceClient
但是这里的 bean 被刷新了:
@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 来刷新。无需为配置类的每个 bean 声明指定 @RefreshScope。我错过了什么吗?
顺便说一句,我通过在 bean 声明中放置断点来检查 bean 是否刷新。
第二个问题:我想我应该只有一个代理 bean 而不是我们在第二种情况下看到的两个 bean?
【问题讨论】:
-
您将拥有 2 个 bean 实例、1 个代理和 1 个实际实例。代理将在刷新后继续存在,并将委托给新创建的实际实例。将
@RefreshScope放在配置上确实会刷新配置,但不会刷新它创建的bean。您需要明确定义要刷新的 bean。这可以通过将所需的类注释为@RefreshScope或将@Bean方法注释为@RefreshScope来完成。
标签: java spring spring-boot configuration spring-cloud-config