Backend Development 10 min read

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.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How to Dynamically Update Spring Boot Properties at Runtime Without Restart

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>&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
  &lt;artifactId&gt;spring-cloud-context&lt;/artifactId&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
  &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
  &lt;artifactId&gt;spring-boot-starter-actuator&lt;/artifactId&gt;
&lt;/dependency&gt;
</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”.

dynamic configurationSpring BootSpring CloudRefreshScopePropertySourcePrototype Bean
Spring Full-Stack Practical Cases
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.