loaders = SpringFactoriesLoader
+ .loadFactories(PropertySourceLoader.class, getClass().getClassLoader());
+
+ //Range loaders (Yaml as the first)
+ int yamlIndex = -1;
+ for (int i = 0; i < loaders.size(); i++) {
+ if (loaders.get(i) instanceof YamlPropertySourceLoader) {
+ yamlIndex = i;
+ break;
+ }
+ }
+
+ // found yaml loader then move to the front
+ if (yamlIndex != -1) {
+ PropertySourceLoader yamlSourceLoader = loaders.remove(yamlIndex);
+ loaders.add(0, yamlSourceLoader);
+ }
+
+ propertySourceLoaders = loaders;
+ }
+
+ public static DaprCloudConfigParserHandler getInstance() {
+ return ParserHandler.HANDLER;
+ }
+
+ /**
+ * Parse Secret using PropertySourceLoaders.
+ *
+ *
+ * if type = doc, will treat all values as a property source (both "properties" or "yaml" format supported)
+ *
+ *
+ *
+ * if type = value, will transform key and value to "key=value" format ("properties" format)
+ *
+ *
+ * @param configName name of the config
+ * @param configValue value of the config
+ * @param type value type
+ * @return property source list
+ */
+ public List> parseDaprCloudConfigData(
+ String configName,
+ Map configValue,
+ DaprCloudConfigType type
+ ) {
+ List> result = new ArrayList<>();
+
+ Map configResults = getConfigResult(configValue, type);
+ String extension = type instanceof DocType ? ((DocType) type).getDocExtension() : ".properties";
+
+ configResults.forEach((key, configResult) -> {
+ for (PropertySourceLoader propertySourceLoader : propertySourceLoaders) {
+ if (!canLoadFileExtension(propertySourceLoader, extension)) {
+ continue;
+ }
+ String fullConfigName = StringUtils.hasText(key) ? configName + "." + key : configName;
+ try {
+ result.addAll(propertySourceLoader.load(fullConfigName, configResult));
+ } catch (IOException ignored) {
+ continue;
+ }
+ return;
+ }
+ });
+
+ return result;
+ }
+
+ private Map getConfigResult(
+ Map configValue,
+ DaprCloudConfigType type
+ ) {
+ Map result = new HashMap<>();
+ if (type instanceof DocType) {
+ configValue.forEach((key, value) -> result.put(key,
+ new ByteArrayResource(value.getBytes(StandardCharsets.UTF_8))));
+ } else {
+ List configList = new ArrayList<>();
+ configValue.forEach((key, value) -> configList.add(String.format("%s=%s", key, value)));
+ result.put("", new ByteArrayResource(String.join("\n", configList).getBytes(StandardCharsets.UTF_8)));
+ }
+ return result;
+ }
+
+ /**
+ * check the current extension can be processed.
+ * @param loader the propertySourceLoader
+ * @param extension file extension
+ * @return if can match extension
+ */
+ private boolean canLoadFileExtension(PropertySourceLoader loader, String extension) {
+ return Arrays.stream(loader.getFileExtensions())
+ .anyMatch((fileExtension) -> StringUtils.endsWithIgnoreCase(extension,
+ fileExtension));
+ }
+
+ private static class ParserHandler {
+
+ private static final DaprCloudConfigParserHandler HANDLER = new DaprCloudConfigParserHandler();
+
+ }
+}
diff --git a/dapr-spring/dapr-spring-cloudconfig/src/main/java/io/dapr/spring/boot/cloudconfig/configdata/config/DaprConfigurationConfigDataLoader.java b/dapr-spring/dapr-spring-cloudconfig/src/main/java/io/dapr/spring/boot/cloudconfig/configdata/config/DaprConfigurationConfigDataLoader.java
new file mode 100644
index 0000000000..c97b6c8cd0
--- /dev/null
+++ b/dapr-spring/dapr-spring-cloudconfig/src/main/java/io/dapr/spring/boot/cloudconfig/configdata/config/DaprConfigurationConfigDataLoader.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2025 The Dapr Authors
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package io.dapr.spring.boot.cloudconfig.configdata.config;
+
+import io.dapr.client.DaprClient;
+import io.dapr.client.domain.ConfigurationItem;
+import io.dapr.client.domain.GetConfigurationRequest;
+import io.dapr.spring.boot.cloudconfig.config.DaprCloudConfigClientManager;
+import io.dapr.spring.boot.cloudconfig.config.DaprCloudConfigProperties;
+import io.dapr.spring.boot.cloudconfig.configdata.DaprCloudConfigParserHandler;
+import org.apache.commons.logging.Log;
+import org.springframework.boot.context.config.ConfigData;
+import org.springframework.boot.context.config.ConfigDataLoader;
+import org.springframework.boot.context.config.ConfigDataLoaderContext;
+import org.springframework.boot.context.config.ConfigDataResourceNotFoundException;
+import org.springframework.boot.logging.DeferredLogFactory;
+import org.springframework.core.env.PropertySource;
+import org.springframework.util.StringUtils;
+import reactor.core.publisher.Mono;
+
+import java.io.IOException;
+import java.time.Duration;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.springframework.boot.context.config.ConfigData.Option.IGNORE_IMPORTS;
+import static org.springframework.boot.context.config.ConfigData.Option.IGNORE_PROFILES;
+import static org.springframework.boot.context.config.ConfigData.Option.PROFILE_SPECIFIC;
+
+public class DaprConfigurationConfigDataLoader implements ConfigDataLoader {
+
+ private final Log log;
+
+ private DaprClient daprClient;
+
+ private DaprCloudConfigProperties daprCloudConfigProperties;
+
+ /**
+ * Create a Config Data Loader to load config from Dapr Configuration api.
+ *
+ * @param logFactory logFactory
+ * @param daprClient Dapr Client created
+ * @param daprCloudConfigProperties Dapr Cloud Config Properties
+ */
+ public DaprConfigurationConfigDataLoader(DeferredLogFactory logFactory, DaprClient daprClient,
+ DaprCloudConfigProperties daprCloudConfigProperties) {
+ this.log = logFactory.getLog(getClass());
+ this.daprClient = daprClient;
+ this.daprCloudConfigProperties = daprCloudConfigProperties;
+ }
+
+
+ /**
+ * Load {@link ConfigData} for the given resource.
+ *
+ * @param context the loader context
+ * @param resource the resource to load
+ * @return the loaded config data or {@code null} if the location should be skipped
+ * @throws IOException on IO error
+ * @throws ConfigDataResourceNotFoundException if the resource cannot be found
+ */
+ @Override
+ public ConfigData load(ConfigDataLoaderContext context, DaprConfigurationConfigDataResource resource)
+ throws IOException, ConfigDataResourceNotFoundException {
+ DaprCloudConfigClientManager daprClientSecretStoreConfigManager =
+ getBean(context, DaprCloudConfigClientManager.class);
+
+ daprClient = DaprCloudConfigClientManager.getDaprClient();
+ daprCloudConfigProperties = daprClientSecretStoreConfigManager.getDaprCloudConfigProperties();
+
+ if (!daprCloudConfigProperties.getEnabled()) {
+ return ConfigData.EMPTY;
+ }
+
+ if (daprCloudConfigProperties.getWaitSidecarEnabled()) {
+ waitForSidecar();
+ }
+
+ return fetchConfig(resource);
+ }
+
+ private void waitForSidecar() throws IOException {
+ try {
+ daprClient.waitForSidecar(daprCloudConfigProperties.getTimeout())
+ .retry(daprCloudConfigProperties.getWaitSidecarRetries())
+ .block();
+ } catch (RuntimeException e) {
+ log.info(e.getMessage(), e);
+ throw new IOException("Failed to wait for sidecar", e);
+ }
+ }
+
+ private ConfigData fetchConfig(DaprConfigurationConfigDataResource resource)
+ throws IOException, ConfigDataResourceNotFoundException {
+ Mono