diff --git a/spring-boot-modules/spring-boot-3-3/pom.xml b/spring-boot-modules/spring-boot-3-3/pom.xml
index c6f43a93c522..5ec0caf9b35b 100644
--- a/spring-boot-modules/spring-boot-3-3/pom.xml
+++ b/spring-boot-modules/spring-boot-3-3/pom.xml
@@ -41,6 +41,25 @@
langchain4j-ollama
${langchain4j.version}
+
+ org.springframework.cloud
+ spring-cloud-starter
+ ${spring-cloud-starter.version}
+
+
+ org.springframework.cloud
+ spring-cloud-starter-config
+ ${spring-cloud-starter.version}
+
+
+ org.springframework.boot
+ spring-boot-starter-actuator
+
+
+ org.awaitility
+ awaitility
+ test
+
@@ -65,5 +84,6 @@
3.2.4
4.7.0
0.33.0
+ 4.1.3
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/UpdatingPropertiesApplication.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/UpdatingPropertiesApplication.java
new file mode 100644
index 000000000000..7a5abb5d3426
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/UpdatingPropertiesApplication.java
@@ -0,0 +1,13 @@
+package com.baeldung.dynamically.updating.properties;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class UpdatingPropertiesApplication {
+
+ public static void main(String[] args) {
+ SpringApplication.run(UpdatingPropertiesApplication.class, args);
+ }
+
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/controllers/PropertyController.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/controllers/PropertyController.java
new file mode 100644
index 000000000000..a3f0a24fb6ac
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/controllers/PropertyController.java
@@ -0,0 +1,29 @@
+package com.baeldung.dynamically.updating.properties.controllers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import com.baeldung.dynamically.updating.properties.services.ExampleBean;
+import com.baeldung.dynamically.updating.properties.services.PropertyUpdaterService;
+
+@RestController
+@RequestMapping("/properties")
+public class PropertyController {
+
+ @Autowired
+ private PropertyUpdaterService propertyUpdaterService;
+
+ @Autowired
+ private ExampleBean exampleBean;
+
+ @PostMapping("/update")
+ public String updateProperty(@RequestParam String key, @RequestParam String value) {
+ propertyUpdaterService.updateProperty(key, value);
+ return "Property updated. Remember to call the actuator /actuator/refresh";
+ }
+
+ @GetMapping("/customProperty")
+ public String getCustomProperty() {
+ return exampleBean.getCustomProperty();
+ }
+}
\ No newline at end of file
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/services/ExampleBean.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/services/ExampleBean.java
new file mode 100644
index 000000000000..06a0347f5b39
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/services/ExampleBean.java
@@ -0,0 +1,17 @@
+package com.baeldung.dynamically.updating.properties.services;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+import org.springframework.stereotype.Component;
+
+@RefreshScope
+@Component
+public class ExampleBean {
+
+ @Value("${my.custom.property}")
+ private String customProperty;
+
+ public String getCustomProperty() {
+ return customProperty;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/services/PropertyUpdaterService.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/services/PropertyUpdaterService.java
new file mode 100644
index 000000000000..4157ec726598
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/services/PropertyUpdaterService.java
@@ -0,0 +1,31 @@
+package com.baeldung.dynamically.updating.properties.services;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.MapPropertySource;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.stereotype.Service;
+
+@Service
+public class PropertyUpdaterService {
+
+ private static final String DYNAMIC_PROPERTIES_SOURCE_NAME = "dynamicProperties";
+
+ @Autowired
+ private ConfigurableEnvironment environment;
+
+ public void updateProperty(String key, String value) {
+ MutablePropertySources propertySources = environment.getPropertySources();
+ if (!propertySources.contains(DYNAMIC_PROPERTIES_SOURCE_NAME)) {
+ Map dynamicProperties = new HashMap<>();
+ dynamicProperties.put(key, value);
+ propertySources.addFirst(new MapPropertySource(DYNAMIC_PROPERTIES_SOURCE_NAME, dynamicProperties));
+ } else {
+ MapPropertySource propertySource = (MapPropertySource) propertySources.get(DYNAMIC_PROPERTIES_SOURCE_NAME);
+ propertySource.getSource().put(key, value);
+ }
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/utility/CustomConfig.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/utility/CustomConfig.java
new file mode 100644
index 000000000000..1f5ea52bd96d
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/utility/CustomConfig.java
@@ -0,0 +1,16 @@
+package com.baeldung.dynamically.updating.properties.utility;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Scope;
+
+@Configuration
+public class CustomConfig {
+
+ @Bean
+ @Scope("prototype")
+ public MyService myService(@Value("${custom.property:default}") String property) {
+ return new MyService(property);
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/utility/MyService.java b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/utility/MyService.java
new file mode 100644
index 000000000000..9cd6c04bedc9
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/main/java/com/baeldung/dynamically/updating/properties/utility/MyService.java
@@ -0,0 +1,14 @@
+package com.baeldung.dynamically.updating.properties.utility;
+
+public class MyService {
+
+ private final String property;
+
+ public MyService(String property) {
+ this.property = property;
+ }
+
+ public String getProperty() {
+ return property;
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties b/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties
index a2c75b9bcc65..2b310bb6a26a 100644
--- a/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties
+++ b/spring-boot-modules/spring-boot-3-3/src/main/resources/application.properties
@@ -12,3 +12,15 @@ ollama.max_response_length=1000
# Logging configuration
logging.level.root=INFO
logging.level.com.baeldung.chatbot=DEBUG
+logging.level.com.baeldung.dynamically.updating.properties=DEBUG
+logging.level.org.springframework.boot.actuate=DEBUG
+
+# We can disable Spring Cloud Config to prevent the application from trying to connect to a configuration server
+spring.cloud.config.enabled=false
+# Enable the Spring Boot Actuator endpoints to trigger a refresh
+management.endpoint.refresh.enabled=true
+management.endpoints.web.exposure.include=refresh
+
+# Example property to be changed at runtime
+my.custom.property=defaultValue
+
diff --git a/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/dynamically/updating/properties/CustomConfigUnitTest.java b/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/dynamically/updating/properties/CustomConfigUnitTest.java
new file mode 100644
index 000000000000..278d96e4399a
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/dynamically/updating/properties/CustomConfigUnitTest.java
@@ -0,0 +1,34 @@
+package com.baeldung.dynamically.updating.properties;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import com.baeldung.dynamically.updating.properties.utility.MyService;
+
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@ExtendWith(SpringExtension.class)
+@SpringBootTest(classes = UpdatingPropertiesApplication.class)
+public class CustomConfigUnitTest {
+
+ @Autowired
+ private ApplicationContext context;
+
+ @Test
+ void whenPropertyInjected_thenServiceUsesCustomProperty() {
+ MyService service = context.getBean(MyService.class);
+ assertEquals("default", service.getProperty());
+ }
+
+ @Test
+ void whenPropertyChanged_thenServiceUsesUpdatedProperty() {
+ System.setProperty("custom.property", "updated");
+ MyService service = context.getBean(MyService.class);
+ assertEquals("updated", service.getProperty());
+ }
+}
diff --git a/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/dynamically/updating/properties/PropertyUpdaterServiceUnitTest.java b/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/dynamically/updating/properties/PropertyUpdaterServiceUnitTest.java
new file mode 100644
index 000000000000..ec94040aa6e8
--- /dev/null
+++ b/spring-boot-modules/spring-boot-3-3/src/test/java/com/baeldung/dynamically/updating/properties/PropertyUpdaterServiceUnitTest.java
@@ -0,0 +1,48 @@
+package com.baeldung.dynamically.updating.properties;
+
+import static org.awaitility.Awaitility.await;
+
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.Timeout;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.web.server.LocalServerPort;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.web.client.RestTemplate;
+
+import com.baeldung.dynamically.updating.properties.services.ExampleBean;
+import com.baeldung.dynamically.updating.properties.services.PropertyUpdaterService;
+
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class PropertyUpdaterServiceUnitTest {
+
+ @Autowired
+ private PropertyUpdaterService propertyUpdaterService;
+
+ @Autowired
+ private ExampleBean exampleBean;
+
+ @LocalServerPort
+ private int port;
+
+ @Test
+ @Timeout(5)
+ public void whenUpdatingProperty_thenPropertyIsUpdatedAndRefreshed() throws InterruptedException {
+ // Injects a new property into the test context
+ propertyUpdaterService.updateProperty("my.custom.property", "newValue");
+
+ // Trigger the refresh by calling the actuator endpoint
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
+ HttpEntity entity = new HttpEntity<>(null, headers);
+ RestTemplate restTemplate = new RestTemplate();
+ restTemplate.postForEntity("http://localhost:" + port + "/actuator/refresh", entity, String.class);
+
+ // Awaitility to wait until the property is updated
+ await().atMost(5, TimeUnit.SECONDS).until(() -> "newValue".equals(exampleBean.getCustomProperty()));
+ }
+}