I have a spring boot application. I am using Spring Cloud Config to externalize properties - through Git. Everything works fine. I would like the beans to be refreshed when I issue the actuator refresh endpoint. Beans are refreshed eagerly as expected by doing the following:
@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
}
}
The only thing not working as expected is when I annotate a Configuration class with @refreshScope (meaning at the class level), beans declared in this class are not refreshed if they don't have themselves @RefreshScope in the bean declaration.
Here the bean is not refreshed:
@Configuration
@RefreshScope
public class DraftsClientConfiguration {
@Bean
MyBean aBean() {
return new MyBean();
}
}
Here is the log from my RefreshListener class: We can see that in this case, there is only one bean that is not proxied.
RefreshListener - Regular Bean: Bean name: draftsServiceClient - Bean class: class com.citi.qi.athena.drafts.DraftsServiceClient
But here the bean is refreshed:
@Configuration
public class DraftsClientConfiguration {
@RefreshScope
@Bean
MyBean aBean() {
return new MyBean();
}
}
In this second case, we have two beans (should it be the case?), one proxied and one not proxied.
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
According to Spring doc, beans should be refreshed by annotating @RefreshScope at the configuration class level. There is no need to specify @RefreshScope for every bean declaration of the configuration class. Am I missing something?
By the way, I am checking if the bean is refreshed or not by putting a breakpoint in the bean declaration.
Second question: I guess I should have only one proxied bean and not two beans as we can see in the second case?
@RefreshScopeon the configuration will indeed refresh the configuration BUT not the beans it created. You need to explicitly define which beans you want to have refreshed. This can be done by either annotating the desired class to be@RefreshScopeor the@Beanmethod to have@RefreshScope. - M. Deinum