How to Refresh Spring Boot Config at Runtime Without Restart
This guide explains why traditional Java apps require restarts for config changes, introduces Spring Boot's @RefreshScope for hot configuration updates, details its core principles, provides step‑by‑step implementation, best practices, troubleshooting tips, and advanced use cases such as dynamic feature toggles and logging level adjustments.
Why dynamic configuration refresh is needed?
In traditional Java applications, modifying a configuration file requires restarting the service, which causes service interruption, loss of in‑memory state, and complex deployment procedures.
Service interruption: the application is unavailable during restart
State loss: temporary data stored in memory is cleared
Operational complexity: a complicated release workflow is needed
Spring Boot's @RefreshScope perfectly solves these issues by enabling hot configuration updates, allowing the application to be reassembled like Lego blocks without downtime.
@RefreshScope Core Principle
1. Working diagram
graph TD
A[Modify configuration file] --> B[Send POST refresh request]
B --> C[/actuator/refresh endpoint]
C --> D[RefreshScope refresh mechanism]
D --> E[Destroy old Bean and create new Bean]
E --> F[New configuration takes effect immediately]2. Key technical details
Scope proxy: creates a dynamic proxy for the Bean to intercept method calls
Configuration binding: when configuration changes, values annotated with @Value are rebound
Bean lifecycle management: Beans marked with @RefreshScope are destroyed and re‑initialized
Complete implementation steps
Step 1: Add required dependencies
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Actuator for refresh endpoint -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Spring Cloud Config support -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>Step 2: Enable refresh mechanism
@SpringBootApplication
@EnableRefreshScope // enable dynamic refresh
public class DynamicConfigApp {
public static void main(String[] args) {
SpringApplication.run(DynamicConfigApp.class, args);
}
}Step 3: Configure application.yml
app:
feature:
enabled: true
timeout: 5000
retry-count: 3
welcome-msg: "Hello, Dynamic Config!"
management:
endpoints:
web:
exposure:
include: refresh,health,infoStep 4: Create a dynamic configuration Bean
@Service
@RefreshScope // mark Bean as refreshable
public class FeatureService {
@Value("${app.feature.enabled}")
private boolean featureEnabled;
@Value("${app.feature.timeout}")
private int timeout;
@Value("${app.feature.retry-count}")
private int retryCount;
@Value("${app.feature.welcome-msg}")
private String welcomeMessage;
public String getFeatureConfig() {
return String.format("""
Feature Enabled: %s
Timeout: %d ms
Retry Count: %d
Message: %s
""", featureEnabled, timeout, retryCount, welcomeMessage);
}
}Step 5: Create a test controller
@RestController
@RequestMapping("/config")
public class ConfigController {
private final FeatureService featureService;
public ConfigController(FeatureService featureService) {
this.featureService = featureService;
}
@GetMapping
public String getConfig() {
return featureService.getFeatureConfig();
}
}Step 6: Trigger configuration refresh
After modifying application.yml, send a POST request to the refresh endpoint:
curl -X POST http://localhost:8080/actuator/refreshExample response (list of changed keys):
["app.feature.timeout", "app.feature.welcome-msg"]Deep dive into @RefreshScope
1. Scope proxy principle (pseudo‑code)
public class RefreshScopeProxy implements ApplicationContextAware {
private Object targetBean;
@Override
public Object invoke(Method method) {
if (configChanged) {
// destroy old bean
context.destroyBean(targetBean);
// create new bean
targetBean = context.getBean(beanName);
}
return method.invoke(targetBean, args);
}
}2. Refresh scope control techniques
Only properties annotated with @Value are refreshed:
@Component
@RefreshScope
public class PaymentService {
@Value("${payment.timeout}")
private int timeout; // refreshed
private final String apiVersion = "v1.0"; // not refreshed
}Whole configuration classes can also be made refreshable:
@Configuration
@RefreshScope
public class AppConfig {
@Bean
@RefreshScope
public FeatureService featureService() {
return new FeatureService();
}
@Value("${app.theme}")
private String theme;
}Production best practices
1. Security hardening
management:
endpoint:
refresh:
enabled: true
endpoints:
web:
exposure:
include: refresh
base-path: /internal
path-mapping:
refresh: secure-refresh
spring:
security:
user:
name: admin
password: $2a$10$NVM0n8ElaRgg7zWO1CxUdei7vWoQP91oGycgVNCY8GQEx.TGx.AaC2. Automatic refresh solutions
Git webhook auto‑refresh or configuration‑center integration (Nacos example):
# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
auto-refresh: trueCommon troubleshooting
Issue 1: Refresh does not take effect
Ensure the Bean is annotated with @RefreshScope Verify the refresh endpoint returns the modified keys
Enable debug logging:
logging.level.org.springframework.cloud=DEBUGIssue 2: Multiple instances are out of sync
Use Spring Cloud Bus to broadcast refresh events:
curl -X POST http://host:port/actuator/bus-refreshIssue 3: Configuration update causes memory leak
Clean up resources in a @PreDestroy method:
@PreDestroy
public void cleanUp() {
// release resources
}Extended scenarios
Dynamic feature toggle: feature.new-checkout.enabled=true Runtime log level adjustment via a Bean with @RefreshScope and @Value("${logging.level.root}") Database connection pool tuning:
spring.datasource.hikari.maximum-pool-size=20Conclusion
By leveraging @RefreshScope, you achieve zero‑downtime configuration updates, instant effect of application parameters, more flexible operations, and optimal resource utilization. Follow the best‑practice recommendations—avoid dynamic refresh for sensitive data, combine with a configuration center, and protect the refresh endpoint in production—to fully harness dynamic configuration in the cloud‑native era.
Java Backend Technology
Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!
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.
