How to Refresh Spring Boot Configurations at Runtime Without Restart
This article explains why dynamic configuration refresh is needed in Spring Boot, details the @RefreshScope mechanism, provides step‑by‑step implementation code, and shares production best practices and troubleshooting tips for zero‑downtime config updates.
1. Why dynamic configuration refresh is needed?
In traditional Java applications, changing a configuration file requires restarting the service, which leads to service interruption, loss of in‑memory state, and complex deployment processes.
Service interruption: the service is unavailable during restart
State loss: temporary data in memory is cleared
Operational complexity: requires elaborate release procedures
Spring Boot's @RefreshScope solves these problems by enabling hot configuration updates, allowing applications to be reassembled like Lego blocks.
2. @RefreshScope core principle
1. Working principle diagram
graph TD
A[修改配置文件] --> B[发送POST刷新请求]
B --> C[/actuator/refresh 端点]
C --> D[RefreshScope 刷新机制]
D --> E[销毁旧Bean并创建新Bean]
E --> F[新配置立即生效]2. Key technical analysis
Scope proxy: creates a dynamic proxy for the bean to intercept method calls
Configuration binding: re‑binds values annotated with @Value when configuration changes
Bean lifecycle management: destroys and re‑initializes beans marked with
@RefreshScope3. Complete implementation steps
Step 1: Add necessary dependencies
<!-- pom.xml -->
<dependencies>
<!-- Spring Boot core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Configuration refresh core -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Config center support -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>Step 2: Enable refresh mechanism
// Main application class
@SpringBootApplication
@EnableRefreshScope // Enable configuration refresh capability
public class DynamicConfigApp {
public static void main(String[] args) {
SpringApplication.run(DynamicConfigApp.class, args);
}
}Step 3: Configure application.yml
## Application base configuration
app:
feature:
enabled: true
timeout: 5000
retry-count: 3
welcome-msg: "Hello, Dynamic Config!"
## Expose refresh endpoint (critical!)
management:
endpoints:
web:
exposure:
include: refresh,health,infoStep 4: Create dynamic configuration bean
@Service
@RefreshScope
public class FeatureService {
// Inject refreshable configuration items
@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 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/refreshThe response lists the keys that were changed, for example:
["app.feature.timeout", "app.feature.welcome-msg"]4. Deep dive into @RefreshScope
1. Scope proxy principle
// Pseudo‑code: how Spring implements dynamic refresh
public class RefreshScopeProxy implements ApplicationContextAware {
private Object targetBean;
@Override
public Object invoke(Method method) {
if (configChanged) {
// 1. Destroy old bean
context.destroyBean(targetBean);
// 2. Recreate bean
targetBean = context.getBean(beanName);
}
return method.invoke(targetBean, args);
}
}2. Refresh scope control techniques
Scenario 1 – only properties annotated with @Value are refreshed:
@Component
@RefreshScope
public class PaymentService {
// Only @Value fields will be refreshed
@Value("${payment.timeout}")
private int timeout;
// Non‑refreshable field
private final String apiVersion = "v1.0";
}Scenario 2 – refresh an entire configuration class:
@Configuration
@RefreshScope
public class AppConfig {
@Bean
@RefreshScope
public FeatureService featureService() {
return new FeatureService();
}
@Value("${app.theme}")
private String theme;
}5. Production best practices
1. Secure the refresh endpoint
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$...2. Automatic refresh solutions
Git webhook auto‑refresh or Nacos config‑center auto‑refresh:
# bootstrap.yml
spring:
cloud:
nacos:
config:
server-addr: localhost:8848
auto-refresh: true6. Common troubleshooting
Problem 1: Configuration not effective after refresh
Check that @RefreshScope is added to the bean.
Verify the refresh endpoint returns the modified keys.
Enable debug logging:
logging.level.org.springframework.cloud=DEBUGProblem 2: Multi‑instance refresh out of sync
# Use Spring Cloud Bus to synchronize refresh
curl -X POST http://host:port/actuator/bus-refreshProblem 3: Configuration update causing memory leak
@PreDestroy
public void cleanUp() {
// Clean up resources
}7. Extended application scenarios
Dynamic feature toggles, runtime log‑level adjustment, and database connection‑pool tuning can also be driven by @RefreshScope:
# Enable new feature instantly
feature.new-checkout.enabled=true
@RefreshScope
public class LogConfig {
@Value("${logging.level.root}")
private String logLevel;
}
# Adjust DB pool size dynamically
spring.datasource.hikari.maximum-pool-size=20Conclusion
Using @RefreshScope provides zero‑downtime configuration updates, immediate effect of application parameters, more flexible operations, and optimal resource utilization. In production, avoid refreshing sensitive data, combine with a configuration center, and protect the refresh endpoint.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
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.
