How to Dynamically Update Spring Boot Properties at Runtime Without Restart
This article explains several strategies for dynamically updating Spring Boot application properties—such as using prototype‑scoped beans, @RefreshScope with Spring Cloud, external configuration files, and custom PropertySource updates—so that changes take effect without restarting the service.
1. Introduction
In many real‑world scenarios, dynamically managing application configuration is a critical requirement. In a micro‑service architecture, different services may need to change configuration at runtime based on user environment, external API data, or evolving business rules.
The application.properties file is static; without restarting the application, its values cannot be changed. Spring Boot, however, provides powerful ways to adjust configuration at runtime without downtime, whether toggling features or updating third‑party settings.
This article introduces several strategies to dynamically update Spring Boot properties without directly modifying the application.properties file.
2. Practical Examples
2.1 Define Bean as Prototype Scope
When you need to adjust a specific bean’s property at runtime without affecting already created instances or the global application state, injecting values with @Value in a @Service class is insufficient because the injection occurs only once.
Instead, define a bean in a @Configuration class using @Bean and set its scope to prototype . This allows the bean’s properties to be modified during execution.
<code>@Configuration
public class AppConfig {
@Bean
// Declare as prototype bean scope
@Scope("prototype")
public UserService userService(@Value("${pack.app.title:}") String title) {
return new UserService(title);
}
}
public class UserService {
private final String title;
public UserService(String title) {
this.title = title;
}
// getters, setters
}
</code>By declaring UserService as prototype, each getBean call returns a new instance, and the title value is injected anew.
<code>@RestController
public class UserController {
@Resource
private ApplicationContext context;
@GetMapping("/update")
public String update() {
// Set system property value; cannot be defined in application.yml
System.setProperty("pack.app.title", "xxxooo-" + new Random().nextInt(10000));
return "update success";
}
@GetMapping("/title")
public String title() {
return this.context.getBean("us", UserService.class).getTitle();
}
}
</code>Each call to getBean obtains a new object, so the title property always reflects the latest value.
2.2 Use @RefreshScope
Spring Cloud provides the @RefreshScope annotation together with the /actuator/refresh endpoint. Invoking this endpoint refreshes all beans annotated with @RefreshScope . The mechanism creates a proxy for the bean; each method call retrieves a fresh bean instance, achieving real‑time property updates.
Add the following dependencies:
<code><dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
</code>Enable the refresh endpoint:
<code>management:
endpoint:
refresh:
enabled: true
endpoints:
web:
exposure:
include: refresh
</code>Optional logging configuration to record each refresh call:
<code>logging:
level:
org.springframework.boot.actuate: debug
</code>Define a bean that will be refreshed:
<code>@RefreshScope
@Component
public class AppComponent {
@Value("${pack.app.title:}")
private String title;
public String getTitle() {
return this.title;
}
}
</code>Update the environment’s PropertySource dynamically:
<code>@Service
public class PackPropertyService {
private static final String PACK_PROPERTIES_SOURCE_NAME = "packDynamicProperties";
private final ConfigurableEnvironment environment;
public PackPropertyService(ConfigurableEnvironment environment) {
this.environment = environment;
}
// Update or add PropertySource
public void updateProperty(String key, String value) {
MutablePropertySources propertySources = environment.getPropertySources();
if (!propertySources.contains(PACK_PROPERTIES_SOURCE_NAME)) {
Map<String, Object> properties = new HashMap<>();
properties.put(key, value);
propertySources.addFirst(new MapPropertySource(PACK_PROPERTIES_SOURCE_NAME, properties));
} else {
MapPropertySource propertySource = (MapPropertySource) propertySources.get(PACK_PROPERTIES_SOURCE_NAME);
propertySource.getSource().put(key, value);
}
}
}
</code>Expose an API to update the property and retrieve the refreshed value:
<code>@RestController
@RequestMapping("/configprops")
public class PropertyController {
private final PackPropertyService pps;
private final AppComponent app;
public PropertyController(PackPropertyService pps, AppComponent app) {
this.pps = pps;
this.app = app;
}
@PostMapping("/update")
public String updateProperty(String key, String value) {
pps.updateProperty(key, value);
return "update success";
}
@GetMapping("/title")
public String title() {
return app.getTitle();
}
}
</code>Workflow: call /configprops/update to modify the property, then invoke /actuator/refresh to refresh beans, and finally call /configprops/title to see the updated value.
2.3 Use External Configuration File
Sometimes configuration must be managed outside the application package to allow continuous updates and distribution across multiple services. Using the same Spring Cloud setup, enable @RefreshScope and the /actuator/refresh endpoint, and place the properties in an external file, e.g., external-config.properties .
Start the service with a JVM argument pointing to the external file:
Initial external file content:
<code>pack.app.title=xxxooo</code>After modifying the file, invoke /actuator/refresh ; the endpoint returns the updated property key, and subsequent calls to /title return the new value.
2.4 Custom Refresh Strategy
For more advanced scenarios, refer to the article “Custom Refresh Configuration File Strategy”.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.