Spring Cloud: Refresh scope bean

RMAG news

Properties of microservice may be changed during execution. A mechanism is available for refresh in Spring Cloud.

Following library is used

Java 17
Spring Framework 6.1.6
Spring Cloud Common 4.1.2

About @RefreshScope annotation

Following is the definition of @RefreshScope

package org.springframework.cloud.context.config.annotation;
// …
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope(“refresh”)
@Documented
public @interface RefreshScope {
// …
}

@RefreshScope (or @scope(“refresh”)) is used for setting a bean with refresh scope. Following example is a component class annotated with @RefreshScope, for accessing URL of a API.

@Component
@RefreshScope
public class ConfigComponent {

private String apiUrl;

public String getApiUrl() {
return apiUrl;
}

@Value(“${api-url}”)
public void setApiUrl(String apiUrl) {
this.apiUrl = apiUrl;
}

}

Two bean definitions are created.

name “configComponent”, a singleton bean which is injected to other component. This is a proxy instance.
name “scopedTarget.configComponent”, a refresh scope bean that is the actual instance. New instance is replaced when refresh action is trigged.

When getApiUrl() method of “configComponent” proxy instance is called, org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept will be called and to lookup “scopedTarget.configComponent” bean in BeanFactory.

Then org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean will be called. Bean “scopedTarget.configComponent” is refresh scope, so the new instance is saved into cache in org.springframework.cloud.context.scope.refresh.RefreshScope.

Trigger beans refresh action

A Spring Boot Actuator endpoint (/actuator/refresh) is available for trigger beans refresh action. For enables it, to add the following into configuration.

management.endpoints.web.exposure.include=refresh

The operation is defined in org.springframework.cloud.context.refresh.ContextRefresher#refresh

public synchronized Set<String> refresh() {
Set<String> keys = refreshEnvironment();
this.scope.refreshAll();
return keys;
}

When it is triggered, first the configuration is reloaded from configuration source provided by such as Spring Cloud Config, Spring Cloud Kubernetes. Then, existing refresh scope beans will be dereferenced and cannot be access furthermore. A new bean will be created at the point of bean method is called by using values of new configuration.

Reference

https://docs.spring.io/spring-cloud-commons/reference/spring-cloud-commons/application-context-services.html#refresh-scope