changedKeys) {
+ for (Field field : getAllDeclaredFields(ClassUtils.getUserClass(bean))) {
+ if (Modifier.isStatic(field.getModifiers()) || Modifier.isFinal(field.getModifiers())) {
+ continue;
+ }
+ String kebabKey = prefix + "." + camelToKebab(field.getName());
+ String plainKey = prefix + "." + field.getName();
+ String matchedKey = changedKeys.contains(kebabKey) ? kebabKey
+ : changedKeys.contains(plainKey) ? plainKey : null;
+ if (matchedKey == null) {
+ continue;
+ }
+ String value = env.getProperty(matchedKey);
+ if (value == null) {
+ continue;
+ }
+ try {
+ field.setAccessible(true);
+ field.set(bean, convertType(field.getType(), value));
+ logger.info("[RefreshScope] refreshed @ConfigurationProperties field: {}.{} = '{}'",
+ bean.getClass().getName(), field.getName(), value);
+ } catch (Exception e) {
+ logger.warn("[RefreshScope] refresh @ConfigurationProperties field {}.{} error: {}",
+ bean.getClass().getName(), field.getName(), e.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/spring/KenaitoPropertyPlaceholderConfigurer.java b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/spring/KenaitoPropertyPlaceholderConfigurer.java
new file mode 100644
index 0000000..548eb74
--- /dev/null
+++ b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/spring/KenaitoPropertyPlaceholderConfigurer.java
@@ -0,0 +1,55 @@
+package cn.odboy.confcenter.spring;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
+
+import cn.odboy.confcenter.ConfigcenterContext;
+
+/**
+ * Spring property placeholder configurer for plain Spring (non-Boot) applications.
+ *
+ * @author odboy
+ * @version 3.0.0
+ * @date 2026-10-21
+ */
+public class KenaitoPropertyPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer
+ implements DisposableBean, ApplicationContextAware {
+
+ private boolean remoteEnabledSet = false;
+
+ private final ConfigcenterContext ccContext = ConfigcenterContext.getInstance();
+
+ public void setRemoteEnabled(boolean remoteEnabled) {
+ ccContext.setRemoteEnabled(remoteEnabled);
+ remoteEnabledSet = true;
+ }
+
+ @Override
+ protected Properties mergeProperties() throws IOException {
+ Properties properties = super.mergeProperties();
+ if (!remoteEnabledSet) {
+ ccContext.setRemoteEnabled(Boolean.parseBoolean(
+ properties.getProperty("kenaito.config.enabled",
+ properties.getProperty("kenaito.configcenter.enabled", "true"))));
+ }
+ ccContext.init(properties, false);
+ ccContext.mergeRemoteProperties(properties);
+ return properties;
+ }
+
+ @Override
+ public void destroy() {
+ ccContext.close();
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ ConfigcenterContext.setApplicationContext(applicationContext);
+ }
+}
diff --git a/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/springboot/KenaitoEnvironmentInitializer.java b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/springboot/KenaitoEnvironmentInitializer.java
new file mode 100644
index 0000000..6ea323f
--- /dev/null
+++ b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/springboot/KenaitoEnvironmentInitializer.java
@@ -0,0 +1,65 @@
+package cn.odboy.confcenter.springboot;
+
+import java.util.Properties;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.env.EnvironmentPostProcessor;
+import org.springframework.core.Ordered;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.PropertiesPropertySource;
+
+import cn.odboy.confcenter.ConfigcenterContext;
+
+/**
+ * Spring Boot environment post processor.
+ *
+ * Initializes the config center before the application context is created and
+ * injects the remote configuration as a high-priority property source.
+ *
+ * Registered through {@code META-INF/spring.factories}, which Spring Boot 3
+ * still supports for {@link EnvironmentPostProcessor} implementations.
+ *
+ * @author odboy
+ * @version 3.0.0
+ * @date 2026-10-21
+ */
+public class KenaitoEnvironmentInitializer implements EnvironmentPostProcessor, Ordered {
+
+ private final ConfigcenterContext ccContext = ConfigcenterContext.getInstance();
+
+ @Override
+ public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
+ if (!ccContext.isRemoteEnabled() || ccContext.isProcessed()) {
+ return;
+ }
+ Properties properties = new Properties();
+ // Extract config center settings from the Spring Environment. The config data
+ // post processor runs earlier, so application.properties is already loaded.
+ environment.getPropertySources().forEach(propertySource -> {
+ if (propertySource instanceof EnumerablePropertySource> enumerable) {
+ for (String key : enumerable.getPropertyNames()) {
+ if (key.startsWith("kenaito.config.")
+ || key.startsWith("kenaito.configcenter.")
+ || key.equals("spring.application.name")) {
+ String value = environment.getProperty(key);
+ if (value != null) {
+ properties.setProperty(key, value);
+ }
+ }
+ }
+ }
+ });
+ ccContext.init(properties, true);
+ ccContext.mergeRemoteProperties(properties);
+ PropertiesPropertySource propertySource =
+ new PropertiesPropertySource(ConfigcenterContext.MANAGER_PROPERTY_SOURCE, properties);
+ environment.getPropertySources().addFirst(propertySource);
+ }
+
+ @Override
+ public int getOrder() {
+ // Run after ConfigDataEnvironmentPostProcessor (HIGHEST_PRECEDENCE + 10).
+ return Ordered.LOWEST_PRECEDENCE;
+ }
+}
diff --git a/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/springboot/KenaitoRefreshAutoConfiguration.java b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/springboot/KenaitoRefreshAutoConfiguration.java
new file mode 100644
index 0000000..a469835
--- /dev/null
+++ b/kenaito-conf-springboot3-client/src/main/java/cn/odboy/confcenter/springboot/KenaitoRefreshAutoConfiguration.java
@@ -0,0 +1,45 @@
+package cn.odboy.confcenter.springboot;
+
+import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+
+import cn.odboy.confcenter.ConfigcenterContext;
+import cn.odboy.confcenter.RefreshScopeRegistry;
+
+/**
+ * Spring Boot 3 auto configuration for config center refresh support.
+ *
+ * Registers a {@link RefreshScopeRegistry} bean post processor and captures the
+ * {@link ApplicationContext} so that remote config changes can update the Spring
+ * environment and refresh {@code @Value} / {@code @ConfigurationProperties} fields
+ * at runtime.
+ *
+ * Registered through
+ * {@code META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports}.
+ *
+ * @author odboy
+ * @version 3.0.0
+ * @date 2026-10-21
+ */
+@AutoConfiguration
+public class KenaitoRefreshAutoConfiguration implements ApplicationContextAware {
+
+ /**
+ * Must be static so the bean post processor is registered before regular beans
+ * are instantiated.
+ */
+ @Bean
+ public static RefreshScopeRegistry kenaitoRefreshScopeRegistry(Environment environment) {
+ RefreshScopeRegistry registry = new RefreshScopeRegistry(environment);
+ ConfigcenterContext.setRefreshScopeRegistry(registry);
+ return registry;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) {
+ ConfigcenterContext.setApplicationContext(applicationContext);
+ }
+}
diff --git a/kenaito-conf-springboot3-client/src/main/resources/META-INF/spring.factories b/kenaito-conf-springboot3-client/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..a58f71e
--- /dev/null
+++ b/kenaito-conf-springboot3-client/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.env.EnvironmentPostProcessor=\
+cn.odboy.confcenter.springboot.KenaitoEnvironmentInitializer
diff --git a/kenaito-conf-springboot3-client/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/kenaito-conf-springboot3-client/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 0000000..78491be
--- /dev/null
+++ b/kenaito-conf-springboot3-client/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.odboy.confcenter.springboot.KenaitoRefreshAutoConfiguration