Refresh Spring Boot Configurations at Runtime Without Restart
This guide explains why dynamic configuration refresh is essential, how Spring Boot’s @RefreshScope works, and provides step‑by‑step instructions—including Maven dependencies, Actuator setup, bean creation, and troubleshooting—to update settings on‑the‑fly without restarting the service.
In traditional Java applications a configuration change requires a service restart, causing downtime and state loss. Spring Boot’s @RefreshScope enables hot‑reloading of configuration so applications can adapt at runtime without interruption.
Why Dynamic Refresh Is Needed
Service interruption: Restart makes the service unavailable.
State loss: In‑memory data is cleared.
Operational complexity: Requires elaborate deployment procedures.
@RefreshScope Core Principle
1. Working Diagram
2. Key Technical Details
Scope proxy: Creates a dynamic proxy for the bean to intercept method calls.
Configuration binding: When configuration changes, values injected with @Value are re‑bound.
Bean lifecycle management: Beans marked with @RefreshScope are destroyed and recreated on refresh.
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
// Main application class
@SpringBootApplication
@EnableRefreshScope // enable dynamic refresh
public class DynamicConfigApp {
public static void main(String[] args) {
SpringApplication.run(DynamicConfigApp.class, args);
}
}Step 3: Configure application.yml
# Application base config
app:
feature:
enabled: true
timeout: 5000
retry-count: 3
welcome-msg: "Hello, Dynamic Config!"
# Expose refresh endpoint
management:
endpoints:
web:
exposure:
include: refresh,health,infoStep 4: Create a Refreshable Bean
@Service
@RefreshScope // bean supports dynamic refresh
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: Add 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 a Refresh
After modifying application.yml, send a POST request to the Actuator endpoint:
curl -X POST http://localhost:8080/actuator/refreshThe response lists the keys that were refreshed, e.g. ["app.feature.timeout", "app.feature.welcome-msg"].
Deep Dive into @RefreshScope
1. Scope Proxy Implementation (pseudo‑code)
public class RefreshScopeProxy implements ApplicationContextAware {
private Object targetBean;
@Override
public Object invoke(Method method) {
if (configChanged) {
context.destroyBean(targetBean);
targetBean = context.getBean(beanName);
}
return method.invoke(targetBean, args);
}
}2. Refresh Scope Control Techniques
Partial bean refresh: Only fields 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
}Configuration class refresh:
@Configuration
@RefreshScope
public class AppConfig {
@Bean
@RefreshScope
public FeatureService featureService() {
return new FeatureService();
}
@Value("${app.theme}")
private String theme;
}Production Best Practices
Secure the refresh endpoint (e.g., custom path, authentication).
Combine with a configuration center such as Nacos or Spring Cloud Config for centralized management.
Enable automatic refresh in Nacos: auto-refresh: true.
Common Issues & 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=DEBUG.
Issue 2: Multi‑instance refresh out of sync
Use Spring Cloud Bus to broadcast a refresh:
curl -X POST http://host:port/actuator/bus-refreshIssue 3: Configuration update causes memory leak
Clean up resources in a @PreDestroy method.
Extended Scenarios
Feature toggles: feature.new-checkout.enabled=true can be turned on/off at runtime.
Dynamic log level: inject ${logging.level.root} into a bean and refresh it.
Database pool tuning: adjust Hikari settings such as spring.datasource.hikari.maximum-pool-size without restart.
Conclusion
By leveraging @RefreshScope, developers achieve zero‑downtime configuration updates, immediate effect of application parameters, more flexible operations, and optimal resource utilization, making Spring Boot applications well‑suited for cloud‑native environments.
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.
Su San Talks Tech
Su San, former staff at several leading tech companies, is a top creator on Juejin and a premium creator on CSDN, and runs the free coding practice site www.susan.net.cn.
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.
