diff --git a/.github/workflows/maven-build.yml b/.github/workflows/maven-build.yml
index f95530a..cc327f3 100644
--- a/.github/workflows/maven-build.yml
+++ b/.github/workflows/maven-build.yml
@@ -20,8 +20,8 @@ jobs:
strategy:
matrix:
java: [ '17' , '21' ]
- maven-profile-spring-boot: [ 'spring-boot-2.4' , 'spring-boot-2.5' , 'spring-boot-2.6' , 'spring-boot-2.7' ,
- 'spring-boot-3.0' , 'spring-boot-3.1' , 'spring-boot-3.2' , 'spring-boot-3.3' ]
+ maven-profile-spring-boot: [ 'spring-boot-3.0' , 'spring-boot-3.1' , 'spring-boot-3.2' ,
+ 'spring-boot-3.3' , 'spring-boot-3.4' ]
steps:
- name: Checkout Source
uses: actions/checkout@v4
@@ -39,6 +39,11 @@ jobs:
--update-snapshots
--file pom.xml
-Drevision=0.0.1-SNAPSHOT
- -DargLine="--add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED"
- -P${{ matrix.maven-profile-spring-boot }}
- test
\ No newline at end of file
+ test
+ --activate-profiles test,coverage,${{ matrix.maven-profile-spring-boot }}
+
+ - name: Upload coverage reports to Codecov
+ uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
+ slug: microsphere-projects/microsphere-spring-boot
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 9203168..e551b45 100644
--- a/.gitignore
+++ b/.gitignore
@@ -65,5 +65,8 @@ compiler/.gradle/*
.extract
.java-version
+# vscode
+.vscode/
+
# others
build.txt
\ No newline at end of file
diff --git a/README.md b/README.md
index 6b23389..c7b0801 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,9 @@
# microsphere-spring-boot
-Microsphere Projects for Spring Boot
+> Microsphere Projects for Spring Boot
+
+[](https://github.com/microsphere-projects/microsphere-spring-boot/actions/workflows/maven-build.yml)
+[](https://app.codecov.io/gh/microsphere-projects/microsphere-spring-boot)
+
+
+[](http://isitmaintained.com/project/microsphere-projects/microsphere-spring-boot "Average time to resolve an issue")
+[](http://isitmaintained.com/project/microsphere-projects/microsphere-spring-boot "Percentage of issues still open")
diff --git a/microsphere-core-spring-boot-starter/pom.xml b/microsphere-core-spring-boot-starter/pom.xml
index cb0af68..1acaa52 100644
--- a/microsphere-core-spring-boot-starter/pom.xml
+++ b/microsphere-core-spring-boot-starter/pom.xml
@@ -43,6 +43,12 @@
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java
index fecf5d5..d9a9708 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java
@@ -8,8 +8,6 @@
import org.springframework.core.env.Environment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
-import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -19,6 +17,7 @@
import static java.util.Arrays.asList;
import static java.util.Collections.emptySet;
import static java.util.Collections.unmodifiableSet;
+import static org.springframework.util.Assert.isInstanceOf;
import static org.springframework.util.StringUtils.collectionToCommaDelimitedString;
import static org.springframework.util.StringUtils.commaDelimitedListToSet;
import static org.springframework.util.StringUtils.hasText;
@@ -103,7 +102,7 @@ private static MutablePropertySources getPropertySources(Environment environment
}
private static ConfigurableEnvironment getConfigurableEnvironment(Environment environment) {
- Assert.isInstanceOf(ConfigurableEnvironment.class, environment);
+ isInstanceOf(ConfigurableEnvironment.class, environment);
return (ConfigurableEnvironment) environment;
}
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java
index 59ac68d..78ab99e 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java
@@ -1,9 +1,8 @@
package io.microsphere.spring.boot.classloading;
import io.microsphere.classloading.BannedArtifactClassLoadingExecutor;
+import io.microsphere.logging.Logger;
import io.microsphere.spring.boot.listener.SpringApplicationRunListenerAdapter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationStartingEvent;
import org.springframework.context.ApplicationListener;
@@ -12,6 +11,8 @@
import java.util.Arrays;
+import static io.microsphere.logging.LoggerFactory.getLogger;
+
/**
* {@link ApplicationStartingEvent ApplicationStartingEvent} {@link ApplicationListener Listener} bans
* the load of Artifacts collision class
@@ -21,7 +22,7 @@
*/
public class BannedArtifactClassLoadingListener extends SpringApplicationRunListenerAdapter implements Ordered {
- private static final Logger logger = LoggerFactory.getLogger(BannedArtifactClassLoadingListener.class);
+ private static final Logger logger = getLogger(BannedArtifactClassLoadingListener.class);
private static final boolean artifactsBanned = Boolean.getBoolean("microsphere.artifacts.banned");
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java
index 96c1879..7865d81 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java
@@ -1,7 +1,6 @@
package io.microsphere.spring.boot.context;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import io.microsphere.logging.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationPreparedEvent;
import org.springframework.context.ApplicationListener;
@@ -13,6 +12,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListSet;
+import static io.microsphere.logging.LoggerFactory.getLogger;
+
/**
* Once execution {@link ApplicationPreparedEvent} {@link ApplicationListener}
*
@@ -24,7 +25,7 @@ public abstract class OnceApplicationPreparedEventListener implements Applicatio
private static Map, Set> listenerProcessedContextIds = new ConcurrentHashMap<>();
- protected final Logger logger = LoggerFactory.getLogger(getClass());
+ protected final Logger logger = getLogger(getClass());
private final Set processedContextIds;
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java
index 3974cf7..a94ff33 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java
@@ -6,11 +6,11 @@
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
-import org.springframework.util.ClassUtils;
import java.util.List;
import static java.util.Arrays.asList;
+import static org.springframework.util.ClassUtils.isPresent;
/**
@@ -25,7 +25,7 @@ public abstract class OnceMainApplicationPreparedEventListener extends OnceAppli
private static final String BOOTSTRAP_APPLICATION_LISTENER_ENABLED_PROPERTY_NAME = "spring.cloud.bootstrap.enabled";
- private static final boolean BOOTSTRAP_APPLICATION_LISTENER_PRESENT = ClassUtils.isPresent(BOOTSTRAP_APPLICATION_LISTENER_CLASS_NAME, null);
+ private static final boolean BOOTSTRAP_APPLICATION_LISTENER_PRESENT = isPresent(BOOTSTRAP_APPLICATION_LISTENER_CLASS_NAME, null);
private static final String BOOTSTRAP_CONTEXT_ID = "bootstrap";
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanContext.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanContext.java
index d9959cb..4d98edf 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanContext.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanContext.java
@@ -17,14 +17,12 @@
package io.microsphere.spring.boot.context.properties.bind;
import io.microsphere.spring.core.convert.support.ConversionServiceResolver;
-import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.source.ConfigurationProperty;
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.convert.ConversionService;
-import org.springframework.util.ClassUtils;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
@@ -34,6 +32,8 @@
import static io.microsphere.spring.boot.context.properties.source.util.ConfigurationPropertyUtils.toDashedForm;
import static org.springframework.beans.BeanUtils.copyProperties;
+import static org.springframework.beans.BeanUtils.getPropertyDescriptors;
+import static org.springframework.util.ClassUtils.isPrimitiveOrWrapper;
/**
* The context for the bean annotated {@link ConfigurationProperties @ConfigurationProperties}
@@ -95,7 +95,7 @@ private void initBinding(Object bean) {
private void initBinding(Class> beanClass, String prefix, Map bindingPropertyNames, String nestedPath) {
if (isCandidateClass(beanClass)) {
- PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(beanClass);
+ PropertyDescriptor[] descriptors = getPropertyDescriptors(beanClass);
int descriptorSize = descriptors.length;
for (int i = 0; i < descriptorSize; i++) {
PropertyDescriptor descriptor = descriptors[i];
@@ -117,7 +117,7 @@ private boolean isCandidateProperty(PropertyDescriptor descriptor) {
}
private boolean isCandidateClass(Class> beanClass) {
- if (ClassUtils.isPrimitiveOrWrapper(beanClass)) {
+ if (isPrimitiveOrWrapper(beanClass)) {
return false;
}
if (beanClass.isInterface() || beanClass.isEnum() || beanClass.isAnnotation() || beanClass.isArray() || beanClass.isSynthetic()) {
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java
index 8a59423..59db6c2 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java
@@ -16,8 +16,7 @@
*/
package io.microsphere.spring.boot.context.properties.bind;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import io.microsphere.logging.Logger;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -30,17 +29,18 @@
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
-import org.springframework.util.Assert;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Supplier;
+import static io.microsphere.logging.LoggerFactory.getLogger;
import static io.microsphere.spring.boot.context.properties.bind.util.BindUtils.isBoundProperty;
import static io.microsphere.spring.boot.context.properties.bind.util.BindUtils.isConfigurationPropertiesBean;
import static io.microsphere.spring.boot.context.properties.source.util.ConfigurationPropertyUtils.getPrefix;
import static io.microsphere.spring.boot.context.properties.util.ConfigurationPropertiesUtils.CONFIGURATION_PROPERTIES_CLASS;
import static io.microsphere.spring.boot.context.properties.util.ConfigurationPropertiesUtils.findConfigurationProperties;
+import static org.springframework.util.Assert.isInstanceOf;
/**
* A {@link BindListener} implementation of {@link ConfigurationProperties @ConfigurationProperties} Bean to publish
@@ -54,7 +54,7 @@
*/
public class EventPublishingConfigurationPropertiesBeanPropertyChangedListener implements BindListener, BeanFactoryPostProcessor, ApplicationContextAware, SmartInitializingSingleton {
- private final static Logger logger = LoggerFactory.getLogger(EventPublishingConfigurationPropertiesBeanPropertyChangedListener.class);
+ private final static Logger logger = getLogger(EventPublishingConfigurationPropertiesBeanPropertyChangedListener.class);
private static final Class CONFIGURABLE_APPLICATION_CONTEXT_CLASS = ConfigurableApplicationContext.class;
@@ -126,7 +126,7 @@ private void initConfigurationPropertiesBeanContexts(ConfigurableListableBeanFac
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
Class expectedType = CONFIGURABLE_APPLICATION_CONTEXT_CLASS;
- Assert.isInstanceOf(expectedType, context, "The 'context' argument is not an instance of " + expectedType.getName());
+ isInstanceOf(expectedType, context, "The 'context' argument is not an instance of " + expectedType.getName());
this.context = expectedType.cast(context);
}
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java
index f25208a..b80aac6 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java
@@ -16,8 +16,7 @@
*/
package io.microsphere.spring.boot.context.properties.metadata;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import io.microsphere.logging.Logger;
import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller;
import org.springframework.context.ResourceLoaderAware;
@@ -28,6 +27,7 @@
import java.io.IOException;
+import static io.microsphere.logging.LoggerFactory.getLogger;
import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;
/**
@@ -38,7 +38,7 @@
*/
public class ConfigurationMetadataReader implements ResourceLoaderAware {
- private final static Logger logger = LoggerFactory.getLogger(ConfigurationMetadataReader.class);
+ private final static Logger logger = getLogger(ConfigurationMetadataReader.class);
public static final String METADATA_PATH = CLASSPATH_ALL_URL_PREFIX + "/META-INF/spring-configuration-metadata.json";
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java
index 898ede2..87584a0 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java
@@ -1,7 +1,6 @@
package io.microsphere.spring.boot.env;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import io.microsphere.logging.Logger;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.logging.LoggingApplicationListener;
@@ -14,7 +13,6 @@
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.util.ObjectUtils;
import java.io.IOException;
import java.net.URL;
@@ -25,11 +23,13 @@
import java.util.Properties;
import java.util.Set;
+import static io.microsphere.logging.LoggerFactory.getLogger;
import static io.microsphere.spring.boot.util.SpringApplicationUtils.getDefaultPropertiesResources;
import static io.microsphere.spring.boot.util.SpringApplicationUtils.getResourceLoader;
-import static io.microsphere.spring.util.PropertySourcesUtils.getDefaultProperties;
-import static io.microsphere.spring.util.ResourceLoaderUtils.getResourcePatternResolver;
+import static io.microsphere.spring.core.env.PropertySourcesUtils.getDefaultProperties;
+import static io.microsphere.spring.core.io.ResourceLoaderUtils.getResourcePatternResolver;
import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactories;
+import static org.springframework.util.ObjectUtils.containsElement;
/**
* Listable {@link ApplicationEnvironmentPreparedEvent} {@link ApplicationListener} Class
@@ -44,7 +44,7 @@ public class DefaultPropertiesApplicationListener implements ApplicationListener
public static final int DEFAULT_ORDER = LoggingApplicationListener.LOWEST_PRECEDENCE - 1;
- private static final Logger logger = LoggerFactory.getLogger(DefaultPropertiesApplicationListener.class);
+ private static final Logger logger = getLogger(DefaultPropertiesApplicationListener.class);
private int order = DEFAULT_ORDER;
@@ -81,7 +81,7 @@ private void loadDefaultPropertiesResources(List propertyS
ResourceLoader resourceLoader,
Map defaultProperties) {
Set defaultPropertiesResources = getDefaultPropertiesResources();
- logger.debug("Start loading from SpringApplicationUtils. GetDefaultPropertiesResources () 'defaultProperties resources: {}", defaultPropertiesResources);
+ logger.debug("Start loading from SpringApplicationUtils.loadDefaultPropertiesResources() 'defaultProperties resources: {}", defaultPropertiesResources);
loadDefaultProperties(defaultPropertiesResources, propertySourceLoaders, resourceLoader, defaultProperties);
}
@@ -178,7 +178,7 @@ private void merge(EnumerablePropertySource> propertySource, MapMercy
+ * @see PropertySourceLoader
+ * @since 1.0.0
+ */
+public class PropertySourceLoaders implements PropertySourceLoader {
+
+ private static final Logger logger = getLogger(PropertySourceLoaders.class);
+
+ private final ResourceLoader resourceLoader;
+
+ private final List loaders;
+
+ public PropertySourceLoaders() {
+ this(getDefaultClassLoader());
+ }
+
+ public PropertySourceLoaders(ClassLoader classLoader) {
+ this(new DefaultResourceLoader(classLoader));
+ }
+
+ public PropertySourceLoaders(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ this.loaders = loadFactories(PropertySourceLoader.class, resourceLoader.getClassLoader());
+ }
+
+ @Override
+ public String[] getFileExtensions() {
+ String[] fileExtensions = loaders.stream()
+ .map(PropertySourceLoader::getFileExtensions)
+ .map(Arrays::asList)
+ .flatMap(List::stream)
+ .toArray(String[]::new);
+ return fileExtensions;
+ }
+
+ @Override
+ public List> load(String name, Resource resource) throws IOException {
+ List> propertySources = new LinkedList<>();
+ URL url = resource.getURL();
+ for (PropertySourceLoader loader : loaders) {
+ if (supports(loader, url)) {
+ propertySources.addAll(loader.load(name, resource));
+ }
+ }
+ return propertySources;
+ }
+
+ /**
+ * Reload the {@link PropertySource} as an instance of {@link PropertySource} with {@link OriginLookup}
+ *
+ * @param propertySource {@link PropertySource}
+ * @return an instance of {@link PropertySource} with {@link OriginLookup}
+ * @throws IOException
+ */
+ public PropertySource> reloadAsOriginTracked(PropertySource> propertySource) throws IOException {
+ if (propertySource instanceof OriginLookup>) {
+ debug("The PropertySource[name : '{}', class : '{}'] is already an instance of OriginLookup",
+ propertySource.getName(), propertySource.getClass().getName());
+ return propertySource;
+ }
+ // the name is source from Resource#getDescription()
+ String name = propertySource.getName();
+ String location = substringBetween(name, "[", "]");
+ // the location or uri can be resolved from FileSystemResource, ClassPathResource and UrlResource
+ if (hasText(location)) {
+ return loadAsOriginTracked(name, location);
+ }
+ return propertySource;
+ }
+
+ /**
+ * Load the {@link PropertySource} as an instance of {@link PropertySource} with {@link OriginLookup}
+ *
+ * @param name the name of {@link PropertySource}
+ * @param location the location of {@link Resource} for {@link PropertySource}
+ * @return an instance of {@link PropertySource} with {@link OriginLookup}
+ * @throws IOException
+ */
+ public PropertySource> loadAsOriginTracked(String name, String location) throws IOException {
+ Resource resource = resourceLoader.getResource(location);
+ List> propertySources = load(name, resource);
+ int size = propertySources.size();
+ if (size > 1) {
+ throw new IllegalStateException("The resource : " + resource + " can load more than one PropertySource");
+ }
+ return propertySources.get(0);
+ }
+
+ private boolean supports(PropertySourceLoader loader, URL resourceURL) {
+ String[] fileExtensions = loader.getFileExtensions();
+ String path = resourceURL.getPath();
+ boolean supported = false;
+ for (String fileExtension : fileExtensions) {
+ if (path.endsWith(fileExtension)) {
+ supported = true;
+ break;
+ }
+ }
+ return supported;
+ }
+
+ private void debug(String messagePattern, Object... args) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(messagePattern, args);
+ }
+ }
+}
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/config/OriginTrackedConfigurationPropertyInitializer.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/config/OriginTrackedConfigurationPropertyInitializer.java
new file mode 100644
index 0000000..f179b4e
--- /dev/null
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/config/OriginTrackedConfigurationPropertyInitializer.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.microsphere.spring.boot.env.config;
+
+import io.microsphere.logging.Logger;
+import io.microsphere.spring.boot.env.PropertySourceLoaders;
+import io.microsphere.spring.context.event.BeanFactoryListenerAdapter;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.boot.env.OriginTrackedMapPropertySource;
+import org.springframework.boot.origin.Origin;
+import org.springframework.boot.origin.OriginLookup;
+import org.springframework.boot.origin.OriginTrackedValue;
+import org.springframework.context.ApplicationContextInitializer;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.core.env.ConfigurableEnvironment;
+import org.springframework.core.env.EnumerablePropertySource;
+import org.springframework.core.env.MutablePropertySources;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.support.ResourcePropertySource;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import static io.microsphere.logging.LoggerFactory.getLogger;
+import static io.microsphere.spring.beans.factory.support.BeanRegistrar.registerBean;
+
+/**
+ * {@link ApplicationContextInitializer} class supports origin tracked configuration property.
+ *
+ * @author Mercy
+ * @see ConfigurableEnvironment
+ * @since ApplicationContextInitializer
+ */
+public class OriginTrackedConfigurationPropertyInitializer implements BeanFactoryListenerAdapter, ApplicationContextInitializer {
+
+ public static final String BEAN_NAME = "originTrackedConfigurationPropertyInitializer";
+
+ private static final Logger logger = getLogger(OriginTrackedConfigurationPropertyInitializer.class);
+
+ private ConfigurableApplicationContext applicationContext;
+
+ private PropertySourceLoaders propertySourceLoaders;
+
+ @Override
+ public void initialize(ConfigurableApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ this.propertySourceLoaders = new PropertySourceLoaders(applicationContext.getClassLoader());
+ ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
+ BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
+ registerBean(registry, BEAN_NAME, this);
+ }
+
+ @Override
+ public void onBeanFactoryConfigurationFrozen(ConfigurableListableBeanFactory beanFactory) {
+ ConfigurableEnvironment environment = applicationContext.getEnvironment();
+ MutablePropertySources propertySources = environment.getPropertySources();
+ initializePropertySources(propertySources);
+ }
+
+ private void initializePropertySources(MutablePropertySources propertySources) {
+ for (PropertySource propertySource : propertySources) {
+ if (isPropertySourceCandidate(propertySource)) {
+ String name = propertySource.getName();
+ try {
+ PropertySource originTrackedPropertySource = createOriginTrackedPropertySource(propertySource);
+ propertySources.replace(name, originTrackedPropertySource);
+ } catch (IOException e) {
+ logger.error("Failed to create the origin tracked PropertySource[name : '{}', class : '{}']",
+ name, propertySource.getClass().getName());
+ }
+ }
+ }
+ }
+
+ private boolean isPropertySourceCandidate(PropertySource propertySource) {
+ return (propertySource instanceof EnumerablePropertySource>) &&
+ !(propertySource instanceof OriginLookup);
+ }
+
+ private PropertySource createOriginTrackedPropertySource(PropertySource propertySource) throws IOException {
+ if (propertySource instanceof ResourcePropertySource) {
+ return propertySourceLoaders.reloadAsOriginTracked(propertySource);
+ }
+
+ EnumerablePropertySource enumerablePropertySource = (EnumerablePropertySource) propertySource;
+ String[] propertyNames = enumerablePropertySource.getPropertyNames();
+ int size = propertyNames.length;
+ Map source = new LinkedHashMap<>(size);
+ for (int i = 0; i < size; i++) {
+ String propertyName = propertyNames[i];
+ Object propertyValue = enumerablePropertySource.getProperty(propertyName);
+ // Skip if propertyValue is OriginTrackedValue
+ if (propertyValue instanceof OriginTrackedValue) {
+ continue;
+ }
+ Origin origin = resolveOrigin(propertySource);
+ // propertyValue with origin
+ propertyValue = OriginTrackedValue.of(propertyValue, origin);
+ source.put(propertyName, propertyValue);
+ }
+ return new OriginTrackedMapPropertySource(propertySource.getName(), source);
+ }
+
+ private Origin resolveOrigin(PropertySource propertySource) {
+ // TODO more Origin implementations
+ return new NamedOrigin(propertySource.getName());
+ }
+
+ static class NamedOrigin implements Origin {
+
+ private final String name;
+
+ NamedOrigin(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
+}
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java
new file mode 100644
index 0000000..44efe6e
--- /dev/null
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.microsphere.spring.boot.env.config.metadata;
+
+import io.microsphere.spring.boot.context.properties.metadata.ConfigurationMetadataReader;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
+import org.springframework.boot.configurationprocessor.metadata.ItemHint;
+import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
+import org.springframework.lang.NonNull;
+import org.springframework.lang.Nullable;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static java.util.Collections.emptyList;
+import static org.springframework.boot.configurationprocessor.metadata.ItemMetadata.ItemType.GROUP;
+import static org.springframework.boot.configurationprocessor.metadata.ItemMetadata.ItemType.PROPERTY;
+
+/**
+ * The Repository for {@link ConfigurationMetadata}
+ *
+ * @author Mercy
+ * @see ConfigurationMetadata
+ * @see ConfigurationMetadataReader
+ * @since 1.0.0
+ */
+public class ConfigurationMetadataRepository implements CommandLineRunner {
+
+ private final ConfigurationMetadataReader configurationMetadataReader;
+
+ private Map namedGroups;
+
+ private Map namedProperties;
+
+ private Map> namedHints;
+
+ public ConfigurationMetadataRepository(ConfigurationMetadataReader configurationMetadataReader) {
+ this.configurationMetadataReader = configurationMetadataReader;
+ }
+
+ @NonNull
+ public Set getPropertyGroups() {
+ return this.namedGroups.keySet();
+ }
+
+ @NonNull
+ public Set getPropertyNames() {
+ return this.namedProperties.keySet();
+ }
+
+ @NonNull
+ public Collection getGroups() {
+ return this.namedGroups.values();
+ }
+
+ @NonNull
+ public Collection getProperties() {
+ return this.namedProperties.values();
+ }
+
+ @Nullable
+ public ItemMetadata getGroup(String name) {
+ return this.namedGroups.get(name);
+ }
+
+ @Nullable
+ public ItemMetadata getProperty(String name) {
+ return this.namedProperties.get(name);
+ }
+
+ @NonNull
+ public List getHints(String name) {
+ return this.namedHints.getOrDefault(name, emptyList());
+ }
+
+ @NonNull
+ public ConfigurationMetadataReader getConfigurationMetadataReader() {
+ return configurationMetadataReader;
+ }
+
+ @Override
+ public void run(String... args) throws Exception {
+ ConfigurationMetadata configurationMetadata = this.configurationMetadataReader.read();
+ // ConfigurationMetadata can't return the underlying items as Map
+ init(configurationMetadata);
+ }
+
+ private void init(ConfigurationMetadata configurationMetadata) {
+ List items = configurationMetadata.getItems();
+ initNamedGroupItems(items);
+ initNamedPropertyItems(items);
+ initNamedHints(configurationMetadata.getHints());
+ }
+
+ private void initNamedGroupItems(List items) {
+ this.namedGroups = createNamedItems(items, GROUP);
+ }
+
+ private void initNamedPropertyItems(List items) {
+ this.namedProperties = createNamedItems(items, PROPERTY);
+ }
+
+ private void initNamedHints(List items) {
+ Map> namedHints = new LinkedHashMap<>(items.size());
+ items.stream().forEach(itemHint -> {
+ List itemHints = namedHints.computeIfAbsent(itemHint.getName(), i -> new LinkedList<>());
+ itemHints.add(itemHint);
+ });
+ this.namedHints = namedHints;
+ }
+
+ private Map createNamedItems(List items, ItemMetadata.ItemType itemType) {
+ Map namedItems = new LinkedHashMap<>(items.size());
+ items.stream().filter(item -> item.isOfItemType(itemType)).forEach(item -> {
+ namedItems.put(item.getName(), item);
+ });
+ return namedItems;
+ }
+}
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/report/ConditionsReportMessageBuilder.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/report/ConditionsReportMessageBuilder.java
index e65ff70..98174ba 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/report/ConditionsReportMessageBuilder.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/report/ConditionsReportMessageBuilder.java
@@ -1,6 +1,5 @@
package io.microsphere.spring.boot.report;
-import io.microsphere.text.FormatUtils;
import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
@@ -11,6 +10,8 @@
import java.util.Map;
import java.util.Set;
+import static io.microsphere.text.FormatUtils.format;
+
/**
* Spring Boot Conditions Report builder
*
@@ -106,6 +107,6 @@ private Set getBasePackages(ConfigurableApplicationContext context) {
}
private void appendLine(StringBuilder stringBuilder, String text, Object... args) {
- stringBuilder.append(FormatUtils.format(text, args)).append(System.lineSeparator());
+ stringBuilder.append(format(text, args)).append(System.lineSeparator());
}
}
diff --git a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/util/SpringApplicationUtils.java b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/util/SpringApplicationUtils.java
index ca9d8f5..6e93f34 100644
--- a/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/util/SpringApplicationUtils.java
+++ b/microsphere-core-spring-boot-starter/src/main/java/io/microsphere/spring/boot/util/SpringApplicationUtils.java
@@ -3,12 +3,13 @@
import org.springframework.boot.SpringApplication;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
-import org.springframework.util.StringUtils;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
+import static org.springframework.util.StringUtils.hasText;
+
/**
* {@link SpringApplication} Utilities class
*
@@ -29,7 +30,7 @@ private SpringApplicationUtils() throws InstantiationException {
* @param resourceLocation "defaultProperties" resource path
*/
public static void addDefaultPropertiesResource(String resourceLocation) {
- if (StringUtils.hasText(resourceLocation)) {
+ if (hasText(resourceLocation)) {
defaultPropertiesResources.add(resourceLocation);
}
}
diff --git a/microsphere-core-spring-boot-starter/src/main/resources/META-INF/spring.factories b/microsphere-core-spring-boot-starter/src/main/resources/META-INF/spring.factories
index fe59ee9..aeb2f19 100644
--- a/microsphere-core-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/microsphere-core-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -1,6 +1,10 @@
# ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer=\
-io.microsphere.spring.boot.report.ConditionEvaluationReportInitializer
+io.microsphere.spring.context.event.EventPublishingBeanInitializer,\
+io.microsphere.spring.boot.report.ConditionEvaluationReportInitializer,\
+io.microsphere.spring.beans.factory.support.ListenableAutowireCandidateResolverInitializer,\
+io.microsphere.spring.core.env.ListenableConfigurableEnvironmentInitializer,\
+io.microsphere.spring.boot.env.config.OriginTrackedConfigurationPropertyInitializer
# SpringApplicationRunListener
org.springframework.boot.SpringApplicationRunListener=\
@@ -27,4 +31,5 @@ io.microsphere.spring.boot.autoconfigure.ConfigurableAutoConfigurationImportFilt
# DefaultPropertiesPostProcessor
io.microsphere.spring.boot.env.DefaultPropertiesPostProcessor=\
-io.microsphere.spring.boot.env.SpringApplicationDefaultPropertiesPostProcessor
\ No newline at end of file
+io.microsphere.spring.boot.env.SpringApplicationDefaultPropertiesPostProcessor
+
diff --git a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/autoconfigure/ApplicationAutoConfigurationTest.java b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/autoconfigure/ApplicationAutoConfigurationTest.java
index 6bf3184..66093b8 100644
--- a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/autoconfigure/ApplicationAutoConfigurationTest.java
+++ b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/autoconfigure/ApplicationAutoConfigurationTest.java
@@ -22,7 +22,6 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
@@ -65,7 +64,7 @@ static class TestConfig {
@Autowired
private ObjectProvider loggingBeanListenerObjectProvider;
- @Resource(name = "io.microsphere.spring.context.event.BeanTimeStatistics#0")
+ @Resource
private BeanTimeStatistics beanTimeStatistics;
@Resource(type = LoggingBeanListener.class)
@@ -77,8 +76,7 @@ public void setLoggingBeanListener(LoggingBeanListener loggingBeanListener) {
}
public TestConfig(ObjectProvider beanListeners,
- ObjectProvider> beanListenersList,
- @Qualifier("io.microsphere.spring.context.event.LoggingBeanListener#0") LoggingBeanListener loggingBeanListener) {
+ ObjectProvider> beanListenersList) {
this.beanListeners = beanListeners;
this.beanListenersList = beanListenersList;
}
diff --git a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinderTest.java b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinderTest.java
index 05ee67a..dbb82f2 100644
--- a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinderTest.java
+++ b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinderTest.java
@@ -28,7 +28,8 @@
import java.util.Map;
-import static io.microsphere.spring.util.PropertySourcesUtils.getSubProperties;
+import static io.microsphere.spring.core.env.PropertySourcesUtils.getSubProperties;
+import static java.lang.Integer.valueOf;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -59,6 +60,6 @@ void testBind() {
Map properties = getSubProperties(environment.getPropertySources(), "user");
beanBinder.bind(properties, true, true, user);
assertEquals("mercyblitz", user.getName());
- assertEquals(37, user.getAge());
+ assertEquals(valueOf(37), user.getAge());
}
}
diff --git a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisorTest.java b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisorTest.java
index 328c753..24faedb 100644
--- a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisorTest.java
+++ b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisorTest.java
@@ -16,10 +16,9 @@
*/
package io.microsphere.spring.boot.context.properties;
+import io.microsphere.logging.Logger;
import io.microsphere.spring.boot.context.properties.bind.BindListener;
import org.junit.jupiter.api.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.context.properties.bind.BindContext;
@@ -29,6 +28,8 @@
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
+import static io.microsphere.logging.LoggerFactory.getLogger;
+
/**
* {@link ListenableConfigurationPropertiesBindHandlerAdvisor} Test
*
@@ -50,7 +51,7 @@
@EnableConfigurationProperties
public class ListenableConfigurationPropertiesBindHandlerAdvisorTest {
- private static final Logger logger = LoggerFactory.getLogger(ListenableConfigurationPropertiesBindHandlerAdvisorTest.class);
+ private static final Logger logger = getLogger(ListenableConfigurationPropertiesBindHandlerAdvisorTest.class);
@Test
public void test() {
diff --git a/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/env/PropertySourceLoadersTest.java b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/env/PropertySourceLoadersTest.java
new file mode 100644
index 0000000..6482b93
--- /dev/null
+++ b/microsphere-core-spring-boot-starter/src/test/java/io/microsphere/spring/boot/env/PropertySourceLoadersTest.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.microsphere.spring.boot.env;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.env.OriginTrackedMapPropertySource;
+import org.springframework.boot.origin.OriginLookup;
+import org.springframework.core.env.PropertySource;
+import org.springframework.core.io.DefaultResourceLoader;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
+
+import java.io.IOException;
+import java.util.List;
+
+import static io.microsphere.util.ArrayUtils.of;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link PropertySourceLoaders}
+ *
+ * @author Mercy
+ * @see PropertySourceLoaders
+ * @since 1.0.0
+ */
+public class PropertySourceLoadersTest {
+
+ private static final PropertySourceLoaders propertySourceLoaders = new PropertySourceLoaders();
+
+ private static final String TEST_PROPERTY_NAME = "core";
+
+ private static final String TEST_RESOURCE_LOCATION = "classpath:/config/default/core.properties";
+
+ @Test
+ public void testGetFileExtensions() {
+ String[] fileExtensions = propertySourceLoaders.getFileExtensions();
+ assertArrayEquals(of("properties", "xml", "yml", "yaml"), fileExtensions);
+ }
+
+ @Test
+ public void testLoad() throws IOException {
+ ResourceLoader resourceLoader = new DefaultResourceLoader();
+ Resource resource = resourceLoader.getResource(TEST_RESOURCE_LOCATION);
+ List> propertySources = propertySourceLoaders.load(TEST_PROPERTY_NAME, resource);
+ assertEquals(1, propertySources.size());
+
+ PropertySource propertySource = propertySources.get(0);
+ assertPropertySource(propertySource);
+ }
+
+ @Test
+ public void testLoadAsOriginTracked() throws IOException {
+ PropertySource propertySource = propertySourceLoaders.loadAsOriginTracked(TEST_PROPERTY_NAME, TEST_RESOURCE_LOCATION);
+ assertTrue(propertySource instanceof OriginLookup);
+ assertPropertySource(propertySource);
+ }
+
+ @Test
+ public void testReloadAsOriginTracked() throws IOException {
+ PropertySource propertySource = propertySourceLoaders.loadAsOriginTracked(TEST_PROPERTY_NAME, TEST_RESOURCE_LOCATION);
+ assertSame(propertySource, propertySourceLoaders.reloadAsOriginTracked(propertySource));
+ }
+
+ private void assertPropertySource(PropertySource> propertySource) {
+ assertTrue(propertySource instanceof OriginTrackedMapPropertySource);
+ assertEquals(TEST_PROPERTY_NAME, propertySource.getName());
+ assertEquals("graceful", propertySource.getProperty("server.shutdown"));
+ }
+}
diff --git a/microsphere-core-spring-boot-starter/src/test/resources/META-INF/spring.factories b/microsphere-core-spring-boot-starter/src/test/resources/META-INF/spring.factories
index c4d0955..3e82d88 100644
--- a/microsphere-core-spring-boot-starter/src/test/resources/META-INF/spring.factories
+++ b/microsphere-core-spring-boot-starter/src/test/resources/META-INF/spring.factories
@@ -9,5 +9,4 @@ io.microsphere.spring.context.event.BeanTimeStatistics
# BeanFactoryListener
io.microsphere.spring.context.event.BeanFactoryListener=\
-io.microsphere.spring.context.event.LoggingBeanFactoryListener,\
-io.microsphere.spring.context.event.ParallelPreInstantiationSingletonsBeanFactoryListener
\ No newline at end of file
+io.microsphere.spring.context.event.LoggingBeanFactoryListener
\ No newline at end of file
diff --git a/microsphere-core-spring-boot-starter/src/test/resources/logback.xml b/microsphere-core-spring-boot-starter/src/test/resources/logback.xml
new file mode 100644
index 0000000..fbbd2bd
--- /dev/null
+++ b/microsphere-core-spring-boot-starter/src/test/resources/logback.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+ ${ENCODER_PATTERN}
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/microsphere-spring-boot-actuator/pom.xml b/microsphere-spring-boot-actuator/pom.xml
index 0d65ebf..3391a58 100644
--- a/microsphere-spring-boot-actuator/pom.xml
+++ b/microsphere-spring-boot-actuator/pom.xml
@@ -27,6 +27,13 @@
${revision}
+
+
+ org.jolokia
+ jolokia-core
+ ${jolokia.version}
+
+
org.springframework.boot
@@ -46,7 +53,19 @@
true
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ test
+
+
org.springframework.boot
spring-boot-starter-test
diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/MonitoredThreadPoolTaskScheduler.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/MonitoredThreadPoolTaskScheduler.java
index 77af057..08064f7 100644
--- a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/MonitoredThreadPoolTaskScheduler.java
+++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/MonitoredThreadPoolTaskScheduler.java
@@ -18,7 +18,6 @@
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics;
-import io.micrometer.core.instrument.internal.TimedScheduledExecutorService;
import io.microsphere.concurrent.DelegatingScheduledExecutorService;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.SmartInitializingSingleton;
@@ -38,7 +37,7 @@
* @author Mercy
* @see ThreadPoolTaskScheduler
* @see ExecutorServiceMetrics
- * @see TimedScheduledExecutorService
+ * @see io.micrometer.core.instrument.internal.TimedScheduledExecutorService
* @since 1.0.0
*/
public class MonitoredThreadPoolTaskScheduler extends ThreadPoolTaskScheduler implements ApplicationContextAware, SmartInitializingSingleton {
diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfiguration.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfiguration.java
index 464a927..428ad89 100644
--- a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfiguration.java
+++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfiguration.java
@@ -16,17 +16,21 @@
*/
package io.microsphere.spring.boot.actuate.autoconfigure;
+import io.microsphere.spring.boot.actuate.condition.ConditionalOnConfigurationProcessorPresent;
import io.microsphere.spring.boot.actuate.endpoint.ArtifactsEndpoint;
+import io.microsphere.spring.boot.actuate.endpoint.ConfigurationMetadataEndpoint;
import io.microsphere.spring.boot.actuate.endpoint.WebEndpoints;
+import io.microsphere.spring.boot.context.properties.metadata.ConfigurationMetadataReader;
+import io.microsphere.spring.boot.env.config.metadata.ConfigurationMetadataRepository;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
-import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints;
import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Import;
/**
* Actuator {@link Endpoint @Endpoint} Auto-Configuration class
@@ -38,6 +42,7 @@
@ConditionalOnClass(name = {
"org.springframework.boot.actuate.endpoint.annotation.Endpoint"
})
+@Import(value = {ActuatorEndpointsAutoConfiguration.ConfigurationProcessorConfiguration.class})
public class ActuatorEndpointsAutoConfiguration implements BeanClassLoaderAware {
private ClassLoader classLoader;
@@ -57,6 +62,30 @@ public WebEndpoints webEndpoints(WebEndpointsSupplier webEndpointsSupplier) {
return new WebEndpoints(webEndpointsSupplier);
}
+ @ConditionalOnConfigurationProcessorPresent
+ static class ConfigurationProcessorConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ConfigurationMetadataReader configurationMetadataReader() {
+ return new ConfigurationMetadataReader();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public ConfigurationMetadataRepository configurationMetadataRepository(ConfigurationMetadataReader configurationMetadataReader) {
+ return new ConfigurationMetadataRepository(configurationMetadataReader);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ @ConditionalOnAvailableEndpoint
+ public ConfigurationMetadataEndpoint configurationMetadataEndpoint(ConfigurationMetadataRepository configurationMetadataRepository) {
+ return new ConfigurationMetadataEndpoint(configurationMetadataRepository);
+ }
+
+ }
+
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/condition/ConditionalOnConfigurationProcessorPresent.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/condition/ConditionalOnConfigurationProcessorPresent.java
new file mode 100644
index 0000000..c45d278
--- /dev/null
+++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/condition/ConditionalOnConfigurationProcessorPresent.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.microsphere.spring.boot.actuate.condition;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.context.annotation.Conditional;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * {@link Conditional @Conditional} that checks whether the artifact "org.springframework.boot:spring-boot-configuration-processor"
+ * is present
+ *
+ * @author Mercy
+ * @see Conditional
+ * @since 1.0.0
+ */
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@ConditionalOnClass(name = "org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata")
+public @interface ConditionalOnConfigurationProcessorPresent {
+}
diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationMetadataEndpoint.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationMetadataEndpoint.java
new file mode 100644
index 0000000..f67e152
--- /dev/null
+++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationMetadataEndpoint.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.microsphere.spring.boot.actuate.endpoint;
+
+import io.microsphere.spring.boot.env.config.metadata.ConfigurationMetadataRepository;
+import org.springframework.boot.actuate.endpoint.OperationResponseBody;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
+import org.springframework.boot.configurationprocessor.metadata.ItemMetadata;
+
+import java.util.Collection;
+
+/**
+ * {@link Endpoint @Endpoint} to expose the {@link ConfigurationMetadata Configuration Metadata} that was generated by
+ * "org.springframework.boot:spring-boot-configuration-processor"
+ *
+ * @author Mercy
+ * @see ConfigurationMetadata
+ * @see ConfigurationMetadataRepository
+ * @since 1.0.0
+ */
+@Endpoint(id = "configMetadata")
+public class ConfigurationMetadataEndpoint {
+
+ private final ConfigurationMetadataRepository configurationMetadataRepository;
+
+ public ConfigurationMetadataEndpoint(ConfigurationMetadataRepository configurationMetadataRepository) {
+ this.configurationMetadataRepository = configurationMetadataRepository;
+ }
+
+ @ReadOperation
+ public ConfigurationMetadataDescriptor getConfigurationMetadata() {
+ ConfigurationMetadataDescriptor configurationMetadata = new ConfigurationMetadataDescriptor();
+ configurationMetadata.groups = this.configurationMetadataRepository.getGroups();
+ configurationMetadata.properties = this.configurationMetadataRepository.getProperties();
+ return configurationMetadata;
+ }
+
+ /**
+ * The Descriptor class for {@link ConfigurationMetadata}
+ */
+ public static class ConfigurationMetadataDescriptor implements OperationResponseBody {
+
+ private Collection groups;
+
+ private Collection properties;
+
+ public Collection getGroups() {
+ return groups;
+ }
+
+ public void setGroups(Collection groups) {
+ this.groups = groups;
+ }
+
+ public Collection getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Collection properties) {
+ this.properties = properties;
+ }
+ }
+}
diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationPropertiesEndpoint.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationPropertiesEndpoint.java
new file mode 100644
index 0000000..8e6c1e0
--- /dev/null
+++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationPropertiesEndpoint.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.microsphere.spring.boot.actuate.endpoint;
+
+import io.microsphere.spring.boot.env.config.metadata.ConfigurationMetadataRepository;
+import io.microsphere.spring.config.ConfigurationProperty;
+import org.springframework.boot.actuate.endpoint.OperationResponseBody;
+import org.springframework.boot.actuate.endpoint.annotation.Endpoint;
+import org.springframework.boot.actuate.endpoint.annotation.ReadOperation;
+import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.event.EventListener;
+
+import java.util.List;
+
+/**
+ * {@link Endpoint @Endpoint} to expose the configuration properties.
+ *
+ * @author Mercy
+ * @see ConfigurationMetadata
+ * @see ConfigurationProperties
+ * @since 1.0.0
+ */
+@Endpoint(id = "configProperties")
+public class ConfigurationPropertiesEndpoint {
+
+ private final ConfigurationMetadataRepository configurationMetadataRepository;
+
+ public ConfigurationPropertiesEndpoint(ConfigurationMetadataRepository configurationMetadataRepository) {
+ this.configurationMetadataRepository = configurationMetadataRepository;
+ }
+
+ @EventListener(ApplicationReadyEvent.class)
+ public void onApplicationReadyEvent(ApplicationReadyEvent event) {
+ ConfigurableApplicationContext context = event.getApplicationContext();
+ }
+
+ @ReadOperation
+ public ConfigurationPropertiesDescriptor getConfigurationProperties() {
+ ConfigurationPropertiesDescriptor configurationProperties = new ConfigurationPropertiesDescriptor();
+ return configurationProperties;
+ }
+
+
+ public static class ConfigurationPropertiesDescriptor implements OperationResponseBody {
+
+ private List configurationProperties;
+
+ public List getConfigurationProperties() {
+ return configurationProperties;
+ }
+
+ public void setConfigurationProperties(List configurationProperties) {
+ this.configurationProperties = configurationProperties;
+ }
+ }
+
+
+}
diff --git a/microsphere-spring-boot-actuator/src/main/resources/META-INF/config/default/endpoints.properties b/microsphere-spring-boot-actuator/src/main/resources/META-INF/config/default/endpoints.properties
index 091964e..8aa300d 100644
--- a/microsphere-spring-boot-actuator/src/main/resources/META-INF/config/default/endpoints.properties
+++ b/microsphere-spring-boot-actuator/src/main/resources/META-INF/config/default/endpoints.properties
@@ -75,6 +75,12 @@ management.endpoint.artifacts.enabled = true
management.endpoints.web.path-mapping.artifacts = microsphere/artifacts
management.endpoint.artifacts.cache.time-to-live = ${microsphere.cache.long-long-time-to-live}
+### WebEndpoints Endpoint
management.endpoint.webEndpoints.enabled = true
management.endpoints.web.path-mapping.webEndpoints = microsphere/web/endpoints
management.endpoint.webEndpoints.cache.time-to-live = ${microsphere.cache.short-time-to-live}
+
+### ConfigurationMetadata Endpoint
+management.endpoint.configMetadata.enabled = true
+management.endpoints.web.path-mapping.configMetadata = microsphere/config/metadata
+management.endpoint.configMetadata.cache.time-to-live = ${microsphere.cache.long-long-time-to-live}
\ No newline at end of file
diff --git a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfigurationTest.java b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfigurationTest.java
index 8c8b1cd..7ce1881 100644
--- a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfigurationTest.java
+++ b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfigurationTest.java
@@ -1,6 +1,7 @@
package io.microsphere.spring.boot.actuate.autoconfigure;
import io.microsphere.spring.boot.actuate.endpoint.ArtifactsEndpoint;
+import io.microsphere.spring.boot.actuate.endpoint.ConfigurationMetadataEndpoint;
import io.microsphere.spring.boot.actuate.endpoint.WebEndpoints;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -9,6 +10,7 @@
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.PropertySource;
+import org.springframework.test.context.TestPropertySource;
import java.util.Map;
@@ -25,10 +27,15 @@
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = {
ActuatorEndpointsAutoConfigurationTest.class,
- })
+ },
+ properties = {
+ "management.endpoint.loggers.enabled=false"
+ }
+)
@PropertySource(value = "classpath:META-INF/config/default/endpoints.properties")
+@TestPropertySource(value = "classpath:META-INF/config/default/endpoints.properties")
@EnableAutoConfiguration
-class ActuatorEndpointsAutoConfigurationTest {
+public class ActuatorEndpointsAutoConfigurationTest {
@Autowired
private ArtifactsEndpoint artifactsEndpoint;
@@ -36,6 +43,9 @@ class ActuatorEndpointsAutoConfigurationTest {
@Autowired
private WebEndpoints webEndpoints;
+ @Autowired
+ private ConfigurationMetadataEndpoint configurationMetadataEndpoint;
+
@Test
void testArtifactsEndpoint() {
assertFalse(artifactsEndpoint.getArtifactMetaInfoList().isEmpty());
@@ -47,6 +57,13 @@ public void testInvokeReadOperations() {
assertFalse(aggregatedResults.isEmpty());
}
+ @Test
+ public void testGetConfigurationMetadata() {
+ ConfigurationMetadataEndpoint.ConfigurationMetadataDescriptor configurationMetadata = configurationMetadataEndpoint.getConfigurationMetadata();
+ assertFalse(configurationMetadata.getGroups().isEmpty());
+ assertFalse(configurationMetadata.getProperties().isEmpty());
+ }
+
public static void main(String[] args) {
new SpringApplicationBuilder(ActuatorEndpointsAutoConfigurationTest.class)
.web(WebApplicationType.SERVLET)
diff --git a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/env/DefaultPropertiesTest.java b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/env/DefaultPropertiesTest.java
index 175ba78..8b38131 100644
--- a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/env/DefaultPropertiesTest.java
+++ b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/env/DefaultPropertiesTest.java
@@ -57,7 +57,7 @@ public void testEndpointsDefaultProperties() {
assertProperty("management.endpoint.httptrace.enabled", "false");
assertProperty("management.endpoint.info.enabled", "true");
assertProperty("management.endpoint.integrationgraph.enabled", "false");
- assertProperty("management.endpoint.loggers.enabled", "true");
+ assertProperty("management.endpoint.loggers.enabled", "false");
assertProperty("management.endpoint.liquibase.enabled", "false");
assertProperty("management.endpoint.metrics.enabled", "true");
assertProperty("management.endpoint.mappings.enabled", "true");
@@ -74,6 +74,6 @@ public void testEndpointsDefaultProperties() {
}
private void assertProperty(String propertyName, String expectedValue) {
- assertEquals(environment.getRequiredProperty(propertyName), expectedValue);
+ assertEquals(expectedValue, environment.getRequiredProperty(propertyName));
}
}
diff --git a/microsphere-spring-boot-actuator/src/test/resources/application.properties b/microsphere-spring-boot-actuator/src/test/resources/application.properties
new file mode 100644
index 0000000..1636c41
--- /dev/null
+++ b/microsphere-spring-boot-actuator/src/test/resources/application.properties
@@ -0,0 +1 @@
+management.endpoint.loggers.enabled = false
\ No newline at end of file
diff --git a/microsphere-spring-boot-parent/pom.xml b/microsphere-spring-boot-parent/pom.xml
index 548a5fc..9e7756c 100644
--- a/microsphere-spring-boot-parent/pom.xml
+++ b/microsphere-spring-boot-parent/pom.xml
@@ -19,7 +19,8 @@
Microsphere Spring Boot Parent
- 2.0.0-SNAPSHOT
+ 0.2.0
+ 1.7.2
@@ -45,34 +46,6 @@
-
- spring-boot-2.4
-
- 2.4.13
-
-
-
-
- spring-boot-2.5
-
- 2.5.15
-
-
-
-
- spring-boot-2.6
-
- 2.6.15
-
-
-
-
- spring-boot-2.7
-
- 2.7.18
-
-
-
spring-boot-3.0
@@ -90,17 +63,24 @@
spring-boot-3.2
- 3.2.7
+ 3.2.12
spring-boot-3.3
+
+ 3.3.7
+
+
+
+
+ spring-boot-3.4
true
- 3.3.1
+ 3.4.1
diff --git a/pom.xml b/pom.xml
index 2bed7fa..4f47016 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
io.github.microsphere-projects
microsphere-build
- 0.0.21
+ 0.1.1
4.0.0