From 4877e82c54364d57290343074d06c6488f19acce Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Fri, 17 Oct 2025 19:56:03 +0800 Subject: [PATCH 1/6] Bump microsphere-spring version to 0.2.3 Updated the microsphere-spring.version property in the parent POM from 0.2.2 to 0.2.3 to use the latest release. --- microsphere-spring-boot-parent/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsphere-spring-boot-parent/pom.xml b/microsphere-spring-boot-parent/pom.xml index 7ba6d72d..c4ea5476 100644 --- a/microsphere-spring-boot-parent/pom.xml +++ b/microsphere-spring-boot-parent/pom.xml @@ -19,7 +19,7 @@ Microsphere Spring Boot Parent - 0.2.2 + 0.2.3 1.7.2 From 0ebf6e7e57e7fc4a0e99dfe0a08b0fd917e192b3 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Sat, 18 Oct 2025 11:30:12 +0800 Subject: [PATCH 2/6] Add config to enable artifact collision diagnosis Introduced a configuration property to control whether artifact collision diagnosis is enabled. Refactored collision detection to log errors and return a map of conflicting artifacts when enabled. --- .../ArtifactsCollisionDiagnosisListener.java | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java index 1dbbfc32..e76e9abf 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java @@ -1,18 +1,29 @@ package io.microsphere.spring.boot.diagnostics; +import io.microsphere.annotation.ConfigurationProperty; import io.microsphere.classloading.Artifact; import io.microsphere.classloading.ArtifactDetector; import io.microsphere.classloading.MavenArtifact; +import io.microsphere.logging.Logger; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.event.ApplicationContextInitializedEvent; import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.io.ResourceLoader; import java.util.List; +import java.util.Map; import java.util.Set; +import java.util.StringJoiner; +import static io.microsphere.annotation.ConfigurationProperty.APPLICATION_SOURCE; import static io.microsphere.collection.CollectionUtils.size; +import static io.microsphere.collection.MapUtils.newLinkedHashMap; import static io.microsphere.collection.SetUtils.newLinkedHashSet; +import static io.microsphere.constants.SeparatorConstants.LINE_SEPARATOR; +import static io.microsphere.logging.LoggerFactory.getLogger; +import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX; import static io.microsphere.spring.boot.util.SpringApplicationUtils.getResourceLoader; /** @@ -23,10 +34,30 @@ */ public class ArtifactsCollisionDiagnosisListener implements ApplicationListener { + private static final Logger logger = getLogger(ArtifactsCollisionDiagnosisListener.class); + + /** + * Whether to enable the Artifacts Collision diagnosis : "microsphere.spring.boot.artifacts-collision.enabled" + */ + @ConfigurationProperty( + type = boolean.class, + defaultValue = "false", + source = APPLICATION_SOURCE + ) + public static final String ENABLED_PROPERTY_NAME = MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX + "artifacts-collision.enabled"; + @Override public void onApplicationEvent(ApplicationContextInitializedEvent event) throws ArtifactsCollisionException { - SpringApplication springApplication = event.getSpringApplication(); - diagnose(springApplication); + if (isEnabled(event)) { + SpringApplication springApplication = event.getSpringApplication(); + diagnose(springApplication); + } + } + + private boolean isEnabled(ApplicationContextInitializedEvent event) { + ConfigurableApplicationContext context = event.getApplicationContext(); + ConfigurableEnvironment environment = context.getEnvironment(); + return environment.getProperty(ENABLED_PROPERTY_NAME, Boolean.class, false); } private void diagnose(SpringApplication springApplication) throws ArtifactsCollisionException { @@ -44,22 +75,31 @@ private void diagnose(ResourceLoader resourceLoader) throws ArtifactsCollisionEx protected Set diagnose(ClassLoader classLoader) { ArtifactDetector detector = new ArtifactDetector(classLoader); List artifacts = detector.detect(false); - // Artifacts conflict set - return getArtifactsCollisionSet(artifacts); + // Artifacts conflict Map + Map artifactsCollisionMap = getArtifactsCollisionMap(artifacts); + if (!artifactsCollisionMap.isEmpty()) { + StringJoiner stringJoiner = new StringJoiner(LINE_SEPARATOR, "-\t", ""); + logger.error("Artifacts collision detected:"); + for (Artifact artifact : artifactsCollisionMap.values()) { + stringJoiner.add(artifact.toString()); + } + logger.error(stringJoiner.toString()); + } + return artifactsCollisionMap.keySet(); } - Set getArtifactsCollisionSet(List artifacts) { + Map getArtifactsCollisionMap(List artifacts) { int size = size(artifacts); - Set artifactsCollisionSet = newLinkedHashSet(); + Map artifactsCollisionMap = newLinkedHashMap(size); Set ids = newLinkedHashSet(size); for (int i = 0; i < size; i++) { Artifact artifact = artifacts.get(i); String id = buildId(artifact); if (!ids.add(id)) { - artifactsCollisionSet.add(id); + artifactsCollisionMap.put(id, artifact); } } - return artifactsCollisionSet; + return artifactsCollisionMap; } private String buildId(Artifact artifact) { From 27de2c4bb00d743e4dbf69e17986541a8c8d2c73 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Sat, 18 Oct 2025 11:30:18 +0800 Subject: [PATCH 3/6] Exclude Zookeeper and Curator from test dependencies Added exclusions for org.apache.zookeeper:zookeeper, org.apache.curator:curator-recipes, and org.apache.curator:curator-test from the microsphere-spring-test test dependency in pom.xml to prevent unnecessary transitive dependencies. --- microsphere-spring-boot-core/pom.xml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/microsphere-spring-boot-core/pom.xml b/microsphere-spring-boot-core/pom.xml index 6637297b..5ec895d3 100644 --- a/microsphere-spring-boot-core/pom.xml +++ b/microsphere-spring-boot-core/pom.xml @@ -65,6 +65,20 @@ io.github.microsphere-projects microsphere-spring-test test + + + org.apache.zookeeper + zookeeper + + + org.apache.curator + curator-recipes + + + org.apache.curator + curator-test + + From fcd26e00cc671dd48e32586ab411cef9356eb2bc Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Sat, 18 Oct 2025 11:30:23 +0800 Subject: [PATCH 4/6] Refactor and expand ArtifactsCollisionDiagnosisListenerTest Split and enhance tests for ArtifactsCollisionDiagnosisListener, including environment setup and property-based activation. Refactored collision set test to use a collision map, updating assertions accordingly. --- ...tifactsCollisionDiagnosisListenerTest.java | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListenerTest.java b/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListenerTest.java index 61ef6063..b909a109 100644 --- a/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListenerTest.java +++ b/microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListenerTest.java @@ -24,12 +24,17 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.event.ApplicationContextInitializedEvent; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.mock.env.MockEnvironment; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.Set; import static io.microsphere.classloading.Artifact.create; +import static io.microsphere.spring.boot.diagnostics.ArtifactsCollisionDiagnosisListener.ENABLED_PROPERTY_NAME; import static io.microsphere.spring.boot.diagnostics.ArtifactsCollisionResourceResolver.disable; import static io.microsphere.spring.boot.diagnostics.ArtifactsCollisionResourceResolver.enable; import static io.microsphere.spring.boot.util.TestUtils.application; @@ -47,20 +52,31 @@ */ class ArtifactsCollisionDiagnosisListenerTest { + private MockEnvironment environment; + private ArtifactsCollisionDiagnosisListener listener; @BeforeEach void setUp() { + this.environment = new MockEnvironment(); this.listener = new ArtifactsCollisionDiagnosisListener(); } @Test - void testOnApplicationEvent() { + void testOnApplicationEventOnDefault() { SpringApplication springApplication = application(); - ApplicationContextInitializedEvent event = new ApplicationContextInitializedEvent(springApplication, EMPTY_STRING_ARRAY, null); + ConfigurableApplicationContext context = new GenericApplicationContext(); + context.setEnvironment(this.environment); + ApplicationContextInitializedEvent event = new ApplicationContextInitializedEvent(springApplication, EMPTY_STRING_ARRAY, context); this.listener.onApplicationEvent(event); } + @Test + void testOnApplicationEvent() { + this.environment.setProperty(ENABLED_PROPERTY_NAME, "true"); + this.testOnApplicationEventOnDefault(); + } + @Test void testOnApplicationEventOnException() { try { @@ -78,11 +94,11 @@ void testDiagnose() { } @Test - void testGetArtifactsCollisionSet() { + void testGetArtifactsCollisionMap() { List artifacts = createArtifacts(); - Set artifactsCollisionSet = this.listener.getArtifactsCollisionSet(artifacts); - assertEquals(1, artifactsCollisionSet.size()); - assertTrue(artifactsCollisionSet.contains("test-artifact")); + Map artifactsCollisionMap = this.listener.getArtifactsCollisionMap(artifacts); + assertEquals(1, artifactsCollisionMap.size()); + assertTrue(artifactsCollisionMap.containsKey("test-artifact")); } private List createArtifacts() { From 8d8700022f5432491995636389f222c4f8c5eba1 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Sat, 18 Oct 2025 11:46:48 +0800 Subject: [PATCH 5/6] Clarify property name prefix in Javadoc Updated the Javadoc for MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX to explicitly state the prefix value for better clarity. --- .../io/microsphere/spring/boot/constants/PropertyConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java index 6c5a7776..cd94d15a 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java @@ -30,7 +30,7 @@ public interface PropertyConstants { /** - * The property name prefix of Microsphere Spring Boot + * The property name prefix of Microsphere Spring Boot : "microsphere.spring.boot." */ String MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_PROPERTY_NAME_PREFIX + "boot."; From 5ec839bfd855631ecca7708ac122cb04a05a1348 Mon Sep 17 00:00:00 2001 From: Mercy Ma Date: Sun, 19 Oct 2025 11:55:25 +0800 Subject: [PATCH 6/6] Refactor Actuator task scheduler property names Introduced PropertyConstants for Actuator property name prefixes and updated ActuatorAutoConfiguration to use new constants for task scheduler pool size and thread name prefix. Updated related tests and documentation. Added usage examples and improved Javadoc for several core classes to clarify their purpose and usage. --- .../MonitoredThreadPoolTaskScheduler.java | 2 +- .../ActuatorAutoConfiguration.java | 52 +++++- .../ActuatorEndpointsAutoConfiguration.java | 2 +- ...tionalOnConfigurationProcessorPresent.java | 2 +- .../actuate/constants/PropertyConstants.java | 38 +++++ .../actuate/endpoint/ArtifactsEndpoint.java | 2 +- .../ActuatorAutoConfigurationTest.java | 4 +- .../constants/PropertyConstantsTest.java | 41 +++++ ...igurableAutoConfigurationImportFilter.java | 14 +- .../BannedArtifactClassLoadingListener.java | 17 +- .../ConditionalOnPropertyPrefix.java | 17 ++ .../condition/OnPropertyPrefixCondition.java | 4 +- .../boot/constants/PropertyConstants.java | 2 +- .../SpringBootPropertyConstants.java | 3 +- ...eMainApplicationPreparedEventListener.java | 2 +- .../OnceApplicationPreparedEventListener.java | 26 ++- ...eMainApplicationPreparedEventListener.java | 22 ++- .../BindableConfigurationBeanBinder.java | 17 +- .../ConfigurationPropertiesBeanInfo.java | 27 ++- ...igurationPropertiesBindHandlerAdvisor.java | 30 ++++ .../context/properties/bind/BindListener.java | 2 +- .../properties/bind/BindListeners.java | 2 +- ...ionPropertiesBeanPropertyChangedEvent.java | 8 +- ...PropertiesBeanPropertyChangedListener.java | 1 - .../bind/util/BindHandlerUtils.java | 5 +- .../properties/bind/util/BindUtils.java | 158 ++++++++++++++++++ .../metadata/ConfigurationMetadataReader.java | 6 + .../util/ConfigurationPropertyUtils.java | 24 ++- .../util/ConfigurationPropertiesUtils.java | 30 +++- .../ArtifactsCollisionDiagnosisListener.java | 27 ++- .../ArtifactsCollisionException.java | 2 +- .../ArtifactsCollisionFailureAnalyzer.java | 2 +- .../DefaultPropertiesApplicationListener.java | 43 ++++- .../env/DefaultPropertiesPostProcessor.java | 28 +++- .../boot/env/PropertySourceLoaders.java | 20 +++ .../ConfigurationMetadataRepository.java | 2 +- ...ureReportSpringApplicationRunListener.java | 2 +- .../LoggingSpringApplicationRunListener.java | 2 +- .../SpringApplicationRunListenerAdapter.java | 2 +- .../ConditionEvaluationReportInitializer.java | 2 +- .../ConditionEvaluationReportListener.java | 2 +- ...EvaluationSpringBootExceptionReporter.java | 2 +- 42 files changed, 644 insertions(+), 52 deletions(-) create mode 100644 microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/constants/PropertyConstants.java create mode 100644 microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/constants/PropertyConstantsTest.java 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 08064f7a..78f0e35d 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 @@ -81,4 +81,4 @@ public void setBeanName(String name) { public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.context = applicationContext; } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java index 3d417524..f3d2d189 100644 --- a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java +++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfiguration.java @@ -16,6 +16,7 @@ */ package io.microsphere.spring.boot.actuate.autoconfigure; +import io.microsphere.annotation.ConfigurationProperty; import io.microsphere.spring.boot.actuate.MonitoredThreadPoolTaskScheduler; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -23,6 +24,8 @@ import org.springframework.context.annotation.Bean; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import static io.microsphere.annotation.ConfigurationProperty.APPLICATION_SOURCE; +import static io.microsphere.spring.boot.actuate.constants.PropertyConstants.TASK_SCHEDULER_PROPERTY_NAME_PREFIX; import static org.springframework.core.Ordered.LOWEST_PRECEDENCE; /** @@ -35,6 +38,48 @@ @AutoConfigureOrder(LOWEST_PRECEDENCE) public class ActuatorAutoConfiguration { + /** + * The default value of {@link ThreadPoolTaskScheduler#setPoolSize(int)} for Actuator : "1" + */ + static final String DEFAULT_TASK_SCHEDULER_POOL_SIZE = "1"; + + /** + * The property name of {@link ThreadPoolTaskScheduler#setPoolSize(int)} for Actuator : + * "microsphere.spring.boot.actuator.task-scheduler.pool-size" + */ + @ConfigurationProperty( + defaultValue = DEFAULT_TASK_SCHEDULER_POOL_SIZE, + source = APPLICATION_SOURCE + ) + static final String TASK_SCHEDULER_POOL_SIZE_PROPERTY_NAME = TASK_SCHEDULER_PROPERTY_NAME_PREFIX + "pool-size"; + + /** + * The {@link Value @Value} expression of {@link ThreadPoolTaskScheduler#setPoolSize(int)} for Actuator : + * "${microsphere.spring.boot.actuator.task-scheduler.pool-size:1}" + */ + static final String TASK_SCHEDULER_POOL_SIZE_VALUE_EXPRESSION = "${" + TASK_SCHEDULER_POOL_SIZE_PROPERTY_NAME + ":" + DEFAULT_TASK_SCHEDULER_POOL_SIZE + "}"; + + /** + * The default thread name prefix of {@link ThreadPoolTaskScheduler} for Actuator : "microsphere-spring-boot-actuator-task-" + */ + static final String DEFAULT_TASK_SCHEDULER_THREAD_NAME_PREFIX = "microsphere-spring-boot-actuator-task-"; + + /** + * The property name of {@link ThreadPoolTaskScheduler#setThreadNamePrefix(String)} for Actuator : + * "microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix" + */ + @ConfigurationProperty( + defaultValue = DEFAULT_TASK_SCHEDULER_THREAD_NAME_PREFIX, + source = APPLICATION_SOURCE + ) + static final String TASK_SCHEDULER_THREAD_NAME_PREFIX_PROPERTY_NAME = TASK_SCHEDULER_PROPERTY_NAME_PREFIX + "thread-name-prefix"; + + /** + * The {@link Value @Value} expression of {@link ThreadPoolTaskScheduler#setThreadNamePrefix(String)} for Actuator : + * "${microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix:microsphere-spring-boot-actuator-task-}" + */ + static final String TASK_SCHEDULER_THREAD_NAME_PREFIX_VALUE_EXPRESSION = "${" + TASK_SCHEDULER_THREAD_NAME_PREFIX_PROPERTY_NAME + ":" + DEFAULT_TASK_SCHEDULER_THREAD_NAME_PREFIX + "}"; + /** * The bean name of {@link ThreadPoolTaskScheduler} for Actuator : "actuatorTaskScheduler" */ @@ -42,13 +87,12 @@ public class ActuatorAutoConfiguration { @Bean(name = ACTUATOR_TASK_SCHEDULER_SERVICE_BEAN_NAME, destroyMethod = "shutdown") public ThreadPoolTaskScheduler actuatorTaskScheduler( - @Value("${microsphere.spring.boot.actuator.task-scheduler.pool-size:1}") int poolSize, - @Value("${microsphere.spring.boot.actuator.task-scheduler.prefix:microsphere-spring-boot-actuator-task-}") String threadNamePrefix) { + @Value(TASK_SCHEDULER_POOL_SIZE_VALUE_EXPRESSION) int poolSize, + @Value(TASK_SCHEDULER_THREAD_NAME_PREFIX_VALUE_EXPRESSION) String threadNamePrefix) { MonitoredThreadPoolTaskScheduler threadPoolTaskScheduler = new MonitoredThreadPoolTaskScheduler(); threadPoolTaskScheduler.setPoolSize(poolSize); threadPoolTaskScheduler.setDaemon(true); threadPoolTaskScheduler.setThreadNamePrefix(threadNamePrefix); return threadPoolTaskScheduler; } - -} +} \ No newline at end of file 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 ba2c8c16..2fea03c0 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 @@ -97,4 +97,4 @@ public ConfigurationPropertiesEndpoint configurationPropertiesEndpoint(Configura public void setBeanClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } -} +} \ No newline at end of file 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 index 1ac6439b..8eb065fa 100644 --- 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 @@ -40,4 +40,4 @@ @Documented @ConditionalOnClass(name = "org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata") public @interface ConditionalOnConfigurationProcessorPresent { -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/constants/PropertyConstants.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/constants/PropertyConstants.java new file mode 100644 index 00000000..1f0402be --- /dev/null +++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/constants/PropertyConstants.java @@ -0,0 +1,38 @@ +/* + * 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.constants; + +import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX; + +/** + * The Property constants for Microsphere Spring Boot Actuator + * + * @author Mercy + * @since 1.0.0 + */ +public interface PropertyConstants { + + /** + * The property name prefix of Microsphere Spring Boot : "microsphere.spring.boot.actuator." + */ + String MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX + "actuator."; + + /** + * The property name prefix of Microsphere Spring Boot Actuator Task Scheduler : "microsphere.spring.boot.actuator.task-scheduler." + */ + String TASK_SCHEDULER_PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX + "task-scheduler."; +} \ No newline at end of file diff --git a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ArtifactsEndpoint.java b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ArtifactsEndpoint.java index 16527c47..2eca2073 100644 --- a/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ArtifactsEndpoint.java +++ b/microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ArtifactsEndpoint.java @@ -28,4 +28,4 @@ public ArtifactsEndpoint(ClassLoader classLoader) { public List getArtifactMetaInfoList() { return artifactDetector.detect(false); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java index 4f72ccbd..2ab862ec 100644 --- a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java +++ b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java @@ -39,7 +39,7 @@ ActuatorAutoConfigurationTest.class }, properties = { "microsphere.spring.boot.actuator.task-scheduler.pool-size=2", - "microsphere.spring.boot.actuator.task-scheduler.prefix=my-prefix", + "microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix=my-prefix", }) @EnableAutoConfiguration @@ -52,7 +52,7 @@ class ActuatorAutoConfigurationTest { @Value("${microsphere.spring.boot.actuator.task-scheduler.pool-size}") private int poolSize; - @Value("${microsphere.spring.boot.actuator.task-scheduler.prefix}") + @Value("${microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix}") private String prefix; @Test diff --git a/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/constants/PropertyConstantsTest.java b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/constants/PropertyConstantsTest.java new file mode 100644 index 00000000..d8952087 --- /dev/null +++ b/microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/constants/PropertyConstantsTest.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.constants; + + +import org.junit.jupiter.api.Test; + +import static io.microsphere.spring.boot.actuate.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX; +import static io.microsphere.spring.boot.actuate.constants.PropertyConstants.TASK_SCHEDULER_PROPERTY_NAME_PREFIX; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link PropertyConstants} Test + * + * @author Mercy + * @see PropertyConstants + * @since 1.0.0 + */ +class PropertyConstantsTest { + + @Test + void testConstants() { + assertEquals("microsphere.spring.boot.actuator.", MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX); + assertEquals("microsphere.spring.boot.actuator.task-scheduler.", TASK_SCHEDULER_PROPERTY_NAME_PREFIX); + } +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java index 379d6dec..27453bb1 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/autoconfigure/ConfigurableAutoConfigurationImportFilter.java @@ -25,7 +25,19 @@ import static org.springframework.util.StringUtils.hasText; /** - * Configurable {@link AutoConfigurationImportFilter} + * Configurable {@link AutoConfigurationImportFilter} for excluding specific Spring Boot auto-configuration classes. + * + *

Example Usage

+ *

Exclude auto-configuration classes via property

+ *
{@code
+ * microsphere.autoconfigure.exclude=com.example.FooAutoConfiguration,com.example.BarAutoConfiguration
+ * }
+ * + *

Programmatically exclude classes

+ *
{@code
+ * ConfigurableAutoConfigurationImportFilter.addExcludedAutoConfigurationClass(environment, "com.example.FooAutoConfiguration");
+ * ConfigurableAutoConfigurationImportFilter.addExcludedAutoConfigurationClasses(environment, "com.example.BarAutoConfiguration", "com.example.BazAutoConfiguration");
+ * }
* * @author Mercy * @since 1.0.0 diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java index dae69d86..8de072e6 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListener.java @@ -23,8 +23,21 @@ import static java.lang.Thread.currentThread; /** - * {@link ApplicationStartingEvent ApplicationStartingEvent} {@link ApplicationListener Listener} bans - * the load of Artifacts collision class + * {@link ApplicationStartingEvent} {@link ApplicationListener} that bans loading of artifact collision classes. + *

Example Usage

+ *

Enable artifact banning via system property

+ *
{@code
+ * -Dmicrosphere.spring.boot.banned-artifacts.enabled=true
+ * }
+ * + *

Register listener in Spring Boot application

+ *
{@code
+ * SpringApplication app = new SpringApplication(MyApplication.class);
+ * app.addListeners(new BannedArtifactClassLoadingListener(app));
+ * app.run(args);
+ * }
+ *

+ * When enabled, this listener will prevent loading of banned artifacts during application startup. * * @author Mercy * @since 1.0.0 diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/ConditionalOnPropertyPrefix.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/ConditionalOnPropertyPrefix.java index c203fe03..154d0e45 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/ConditionalOnPropertyPrefix.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/ConditionalOnPropertyPrefix.java @@ -28,6 +28,23 @@ /** * {@link Conditional} that checks if the prefix of properties are found in environment.. * + *

Example Usage

+ *

Single prefix

+ *
{@code
+ * @ConditionalOnPropertyPrefix("myapp.config")
+ * public class MyConfig {
+ *     // This bean will only be loaded if any property with prefix "myapp.config." exists
+ * }
+ * }
+ * + *

Multiple prefixes

+ *
{@code
+ * @ConditionalOnPropertyPrefix( {"feature.alpha", "feature.beta"} )
+ * public class FeatureConfig {
+ *     // Loaded if any property with prefix "feature.alpha." or "feature.beta." exists
+ * }
+ * }
+ * * @author
Mercy * @see OnPropertyPrefixCondition * @since 1.0.0 diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/OnPropertyPrefixCondition.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/OnPropertyPrefixCondition.java index caaf4fc6..3458e0a2 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/OnPropertyPrefixCondition.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/OnPropertyPrefixCondition.java @@ -40,7 +40,7 @@ * @see ConditionalOnPropertyPrefix * @since 1.0.0 */ -public class OnPropertyPrefixCondition extends SpringBootCondition { +class OnPropertyPrefixCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { @@ -64,4 +64,4 @@ public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeM return noMatched ? noMatch("The prefix values " + arrayToString(prefixValues) + " were not found in Environment!") : match(); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java index cd94d15a..6e274130 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java @@ -47,4 +47,4 @@ public interface PropertyConstants { source = APPLICATION_SOURCE ) String MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME = MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX + "logging.level"; -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/SpringBootPropertyConstants.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/SpringBootPropertyConstants.java index 20a7209c..fc9f5859 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/SpringBootPropertyConstants.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/SpringBootPropertyConstants.java @@ -28,5 +28,4 @@ public interface SpringBootPropertyConstants { * @see ConfigurationPropertySources#ATTACHED_PROPERTY_SOURCE_NAME */ String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties"; - -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/LoggingOnceMainApplicationPreparedEventListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/LoggingOnceMainApplicationPreparedEventListener.java index fc788036..fe549410 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/LoggingOnceMainApplicationPreparedEventListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/LoggingOnceMainApplicationPreparedEventListener.java @@ -39,4 +39,4 @@ public LoggingOnceMainApplicationPreparedEventListener() { protected void onApplicationEvent(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context) { log(springApplication, args, context, "onApplicationPreparedEvent"); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java index ac36fea6..e4ec7281 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java @@ -15,7 +15,29 @@ import static io.microsphere.logging.LoggerFactory.getLogger; /** - * Once execution {@link ApplicationPreparedEvent} {@link ApplicationListener} + * This abstract class provides a base implementation for application listeners that should only + * execute once per application context. It handles the logic of tracking which contexts have + * already been processed to prevent duplicate execution. + * + *

Example Usage

+ *
{@code
+ * public class MyOnceApplicationPreparedEventListener extends OnceApplicationPreparedEventListener {
+ *
+ *     @Override
+ *     protected boolean isIgnored(SpringApplication springApplication, String[] args,
+ *                               ConfigurableApplicationContext context) {
+ *         // Return true to skip processing for this context
+ *         return false; // Process all contexts by default
+ *     }
+ *
+ *     @Override
+ *     protected void onApplicationEvent(SpringApplication springApplication, String[] args,
+ *                                     ConfigurableApplicationContext context) {
+ *         // Your one-time initialization logic here
+ *         System.out.println("Application prepared event handled once for context: " + context.getId());
+ *     }
+ * }
+ * }
* * @author Mercy * @see io.microsphere.spring.context.event.OnceApplicationContextEventListener @@ -87,4 +109,4 @@ public final int getOrder() { private static Set getProcessedContextIds(Class listenerClass) { return listenerProcessedContextIds.computeIfAbsent(listenerClass, type -> new ConcurrentSkipListSet<>()); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java index 7eb354c4..9ea86191 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java @@ -12,9 +12,27 @@ /** - * Once execution {@link ApplicationPreparedEvent} {@link ApplicationListener} for Main {@link ApplicationContext} + * Once execution {@link ApplicationPreparedEvent} {@link ApplicationListener} for Main {@link ApplicationContext}. + *

+ * This listener is designed to execute only once for the main application context, ignoring any bootstrap contexts + * that might be created by Spring Cloud. It extends {@link OnceApplicationPreparedEventListener} to provide + * specialized behavior for main application contexts. + * + *

Example Usage

+ *
{@code
+ * public class MyMainApplicationListener extends OnceMainApplicationPreparedEventListener {
+ *
+ *     @Override
+ *     protected void onMainApplicationPrepared(SpringApplication springApplication, String[] args,
+ *                                              ConfigurableApplicationContext context) {
+ *         // Your custom logic here - this will only execute for the main application context
+ *         System.out.println("Main application context is prepared: " + context.getApplicationName());
+ *     }
+ * }
+ * }
* * @author
Mercy + * @see OnceApplicationPreparedEventListener * @since 1.0.0 */ public abstract class OnceMainApplicationPreparedEventListener extends OnceApplicationPreparedEventListener { @@ -78,4 +96,4 @@ private boolean isBootstrapApplicationListenerPresent(ConfigurableApplicationCon ClassLoader classLoader = context.getClassLoader(); return isPresent(BOOTSTRAP_APPLICATION_LISTENER_CLASS_NAME, classLoader); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinder.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinder.java index cb4799f2..90e030a9 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinder.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinder.java @@ -29,16 +29,29 @@ import java.util.Map; +import static io.microsphere.collection.Lists.ofList; import static io.microsphere.spring.boot.context.properties.bind.util.BindHandlerUtils.createBindHandler; import static java.util.Arrays.asList; import static org.springframework.boot.context.properties.bind.Bindable.ofInstance; import static org.springframework.boot.context.properties.source.ConfigurationPropertySources.from; /** - * {@link Bindable} {@link ConfigurationBeanBinder} based on Spring Boot 2 {@link Binder} + * A {@link ConfigurationBeanBinder} implementation based on Spring Boot 2's {@link Binder}, + * which binds configuration properties to a given bean using {@link Bindable}. + * + *

Example Usage

+ *
{@code
+ *     Map properties = new HashMap<>();
+ *     properties.put("app.name", "demo");
+ *     MyConfigBean bean = new MyConfigBean();
+ *     BindableConfigurationBeanBinder binder = new BindableConfigurationBeanBinder();
+ *     binder.bind(properties, true, true, bean);
+ *     // bean.getAppName() == "demo"
+ * }
* * @author
Mercy * @see DefaultConfigurationBeanBinder + * @see ConfigurationBeanBinder * @since 1.0.0 */ public class BindableConfigurationBeanBinder implements ConfigurationBeanBinder { @@ -54,7 +67,7 @@ public void setConversionService(ConversionService conversionService) { public void bind(Map configurationProperties, boolean ignoreUnknownFields, boolean ignoreInvalidFields, Object configurationBean) { - Iterable> propertySources = asList(new MapPropertySource("internal", configurationProperties)); + Iterable> propertySources = ofList(new MapPropertySource("internal", configurationProperties)); // Converts ConfigurationPropertySources Iterable configurationPropertySources = from(propertySources); diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ConfigurationPropertiesBeanInfo.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ConfigurationPropertiesBeanInfo.java index d4397c70..d7c4036d 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ConfigurationPropertiesBeanInfo.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ConfigurationPropertiesBeanInfo.java @@ -32,7 +32,30 @@ import static org.springframework.util.StringUtils.hasText; /** - * The information class for introspecting the bean annotated {@link ConfigurationProperties @ConfigurationProperties} + * The information class for introspecting the bean annotated {@link ConfigurationProperties @ConfigurationProperties}. + * + *

Example Usage

+ *
{@code
+ * // Create instance with bean class only
+ * ConfigurationPropertiesBeanInfo info = new ConfigurationPropertiesBeanInfo(MyConfiguration.class);
+ *
+ * // Create instance with bean class and annotation
+ * ConfigurationProperties annotation = MyConfiguration.class.getAnnotation(ConfigurationProperties.class);
+ * ConfigurationPropertiesBeanInfo info = new ConfigurationPropertiesBeanInfo(MyConfiguration.class, annotation);
+ *
+ * // Create instance with all parameters
+ * ConfigurationPropertiesBeanInfo info = new ConfigurationPropertiesBeanInfo(
+ *     MyConfiguration.class,
+ *     annotation,
+ *     "my.config.prefix"
+ * );
+ *
+ * // Access properties
+ * Class beanClass = info.getBeanClass();
+ * String prefix = info.getPrefix();
+ * List descriptors = info.getPropertyDescriptors();
+ * PropertyDescriptor descriptor = info.getPropertyDescriptor("propertyName");
+ * }
* * @author Mercy * @see ConfigurationProperties @@ -128,4 +151,4 @@ public String toString() { sb.append('}'); return sb.toString(); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisor.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisor.java index 11f8db11..f2f11b47 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisor.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisor.java @@ -33,6 +33,36 @@ /** * {@link ConfigurationPropertiesBindHandlerAdvisor} supports the chaining of the {@link BindListener BindListeners' beans} * + *

Example Usage

+ *
{@code
+ * @Component
+ * public class MyBindListener implements BindListener {
+ *
+ *     @Override
+ *     public void onStart(ConfigurationPropertyName name, Bindable target, BindContext context) {
+ *         System.out.println("Binding started for: " + name);
+ *     }
+ *
+ *     @Override
+ *     public Object onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) {
+ *         System.out.println("Binding succeeded for: " + name);
+ *         return result;
+ *     }
+ *
+ *     @Override
+ *     public Object onFailure(ConfigurationPropertyName name, Bindable target, BindContext context, Exception error) {
+ *         System.out.println("Binding failed for: " + name + ", error: " + error.getMessage());
+ *         return null;
+ *     }
+ * }
+ * }
+ * + *

+ * Multiple listeners can be registered as Spring beans and will be automatically discovered and applied + * in order according to their {@link org.springframework.core.annotation.Order} annotation or + * {@link org.springframework.core.Ordered} interface implementation. + *

+ * * @author Mercy * @see ConfigurationPropertiesBindHandlerAdvisor * @see BindHandler diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListener.java index ad06d767..a722e3ac 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListener.java @@ -91,4 +91,4 @@ default void onFailure(ConfigurationPropertyName name, Bindable target, BindC default void onFinish(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListeners.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListeners.java index ceaab221..4b54ba77 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListeners.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListeners.java @@ -64,4 +64,4 @@ public void onFinish(ConfigurationPropertyName name, Bindable target, BindCon private void iterate(Consumer listenerConsumer) { listeners.forEach(listenerConsumer); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanPropertyChangedEvent.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanPropertyChangedEvent.java index 44aab6df..16d941a4 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanPropertyChangedEvent.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanPropertyChangedEvent.java @@ -21,14 +21,16 @@ import org.springframework.boot.context.properties.source.ConfigurationProperty; /** - * Event raised when the property of bean annotated {@link ConfigurationProperties @ConfigurationProperties} was changed + * Event raised when the property of bean annotated {@link ConfigurationProperties @ConfigurationProperties} was changed. * + * @param the type of the bean annotated with {@link ConfigurationProperties} * @author Mercy * @see ConfigurationProperties * @see BeanPropertyChangedEvent + * @see EventPublishingConfigurationPropertiesBeanPropertyChangedListener * @since 1.0.0 */ -public class ConfigurationPropertiesBeanPropertyChangedEvent extends BeanPropertyChangedEvent { +public class ConfigurationPropertiesBeanPropertyChangedEvent extends BeanPropertyChangedEvent { private final ConfigurationProperty configurationProperty; @@ -40,4 +42,4 @@ public ConfigurationPropertiesBeanPropertyChangedEvent(Object bean, String prope public ConfigurationProperty getConfigurationProperty() { return configurationProperty; } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java index 5fae0574..93b2d5e3 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/EventPublishingConfigurationPropertiesBeanPropertyChangedListener.java @@ -64,7 +64,6 @@ public class EventPublishingConfigurationPropertiesBeanPropertyChangedListener i private boolean bound = false; - @Override public void onStart(ConfigurationPropertyName name, Bindable target, BindContext context) { if (isBound()) { diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindHandlerUtils.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindHandlerUtils.java index a262b585..16856b83 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindHandlerUtils.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindHandlerUtils.java @@ -18,6 +18,7 @@ package io.microsphere.spring.boot.context.properties.bind.util; import io.microsphere.annotation.Nonnull; +import io.microsphere.util.Utils; import org.springframework.boot.context.properties.bind.BindHandler; import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler; import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler; @@ -34,7 +35,7 @@ * @see NoUnboundElementsBindHandler * @since 1.0.0 */ -public abstract class BindHandlerUtils { +public abstract class BindHandlerUtils implements Utils { /** * Create a {@link BindHandler} instance based on the given flags. @@ -73,4 +74,4 @@ public static BindHandler createBindHandler(boolean ignoreUnknownFields, boolean private BindHandlerUtils() { } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindUtils.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindUtils.java index c75425d0..599b572a 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindUtils.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindUtils.java @@ -44,23 +44,181 @@ */ public abstract class BindUtils implements Utils { + /** + * Checks if the given {@link Bindable} target and {@link BindContext} represent a bean + * annotated with {@link ConfigurationProperties} at the root binding level. + * + *

Example Usage

+ *

Example 1: Should return true

+ *
{@code
+     * @ConfigurationProperties(prefix = "app")
+     * public class AppProperties {}
+     * boolean result = isConfigurationPropertiesBean(
+     *     Bindable.of(AppProperties.class).withAnnotation(ConfigurationProperties.class),
+     *     mockBindContextWithDepth(0)
+     * );
+     * }
+ * + *

Example 2: Should return false (not a ConfigurationProperties bean)

+ *
{@code
+     * boolean result2 = isConfigurationPropertiesBean(
+     *     Bindable.of(String.class),
+     *     mockBindContextWithDepth(0)
+     * );
+     * }
+ * + *

Example 3: Should return false (not at root level)

+ *
{@code
+     * boolean result3 = isConfigurationPropertiesBean(
+     *     Bindable.of(AppProperties.class).withAnnotation(ConfigurationProperties.class),
+     *     mockBindContextWithDepth(1)
+     * );
+     * }
+ * + * @param target the bindable target to check, may be {@code null} + * @param context the bind context to check, may be {@code null} + * @return {@code true} if the target has {@link ConfigurationProperties} annotation and context is at root level, + * {@code false} otherwise + * @see #isConfigurationPropertiesBean(BindContext) + * @see ConfigurationProperties + * @see BindContext#getDepth() + */ public static boolean isConfigurationPropertiesBean(Bindable target, BindContext context) { return target != null && target.getAnnotation(CONFIGURATION_PROPERTIES_CLASS) != null && isConfigurationPropertiesBean(context); } + /** + * Checks if the given {@link BindContext} represents a bean annotated with {@link ConfigurationProperties} + * at the root binding level (depth = 0). + * + *

Example Usage

+ *

Example 1: Should return true

+ *
{@code
+     * boolean result = isConfigurationPropertiesBean(mockBindContextWithDepth(0));
+     * }
+ * + *

Example 2: Should return false (not at root level)

+ *
{@code
+     * boolean result = isConfigurationPropertiesBean(mockBindContextWithDepth(1));
+     * }
+ * + *

Example 3: Should return false (null context)

+ *
{@code
+     * boolean result = isConfigurationPropertiesBean(null);
+     * }
+ * + * @param context the bind context to check, may be {@code null} + * @return {@code true} if the context is not null and at root level (depth = 0), + * {@code false} otherwise + * @see BindContext#getDepth() + */ public static boolean isConfigurationPropertiesBean(BindContext context) { return context != null && context.getDepth() == 0; } + /** + * Checks if the given {@link BindContext} represents a bound property. + * + *

Example Usage

+ *

Example 1: Should return true

+ *
{@code
+     * boolean result = isBoundProperty(mockBindContextWithDepth(1));
+     * }
+ * + *

Example 2: Should return false (at root level)

+ *
{@code
+     * boolean result = isBoundProperty(mockBindContextWithDepth(0));
+     * }
+ * + *

Example 3: Should return false (null context)

+ *
{@code
+     * boolean result = isBoundProperty(null);
+     * }
+ * + * @param context the bind context to check, may be {@code null} + * @return {@code true} if the context is not null and depth is greater than 0, + * {@code false} otherwise + * @see BindContext#getDepth() + */ public static boolean isBoundProperty(BindContext context) { return context != null && context.getDepth() > 0; } + /** + * Bind configuration properties to a target type using the provided environment and property name prefix. + * + *

Example Usage

+ *

Example 1: Basic usage with Environment

+ *
{@code
+     * @ConfigurationProperties(prefix = "app")
+     * public class AppProperties {
+     *     private String name;
+     *     // getters and setters
+     * }
+     *
+     * AppProperties properties = BindUtils.bind(environment, "app", AppProperties.class);
+     * }
+ * + *

Example 2: With bind listeners

+ *
{@code
+     * AppProperties properties = BindUtils.bind(environment, "app", AppProperties.class,
+     *     (bindable, context, value) -> {
+     *         // Handle bind event
+     *     });
+     * }
+ * + * @param environment the environment to bind from, must not be {@code null} + * @param propertyNamePrefix the property name prefix to use, may be {@code null} + * @param targetType the target type to bind to, must not be {@code null} + * @param bindListeners optional bind listeners to register for bind events + * @param the target type + * @return the bound instance or {@code null} if binding failed + * @see Environment + * @see BindListener + * @see #bind(Binder, String, Class, BindListener...) + */ public static T bind(Environment environment, String propertyNamePrefix, Class targetType, BindListener... bindListeners) { Binder binder = get(environment); return bind(binder, propertyNamePrefix, targetType, bindListeners); } + /** + * Bind configuration properties to a target type using the provided properties map and property name prefix. + * + *

Example Usage

+ *

Example 1: Basic usage with Map

+ *
{@code
+     * @ConfigurationProperties(prefix = "app")
+     * public class AppProperties {
+     *     private String name;
+     *     // getters and setters
+     * }
+     *
+     * Map properties = new HashMap<>();
+     * properties.put("app.name", "MyApp");
+     * AppProperties appProps = BindUtils.bind(properties, "app", AppProperties.class);
+     * }
+ * + *

Example 2: With bind listeners

+ *
{@code
+     * Map properties = new HashMap<>();
+     * properties.put("app.name", "MyApp");
+     * AppProperties appProps = BindUtils.bind(properties, "app", AppProperties.class,
+     *     (bindable, context, value) -> {
+     *         // Handle bind event
+     *     });
+     * }
+ * + * @param properties the properties map to bind from, must not be {@code null} + * @param propertyNamePrefix the property name prefix to use, may be {@code null} + * @param targetType the target type to bind to, must not be {@code null} + * @param bindListeners optional bind listeners to register for bind events + * @param the target type + * @return the bound instance or {@code null} if binding failed + * @see Map + * @see BindListener + * @see #bind(Binder, String, Class, BindListener...) + */ public static T bind(Map properties, String propertyNamePrefix, Class targetType, BindListener... bindListeners) { ConfigurationPropertySource propertySource = new MapConfigurationPropertySource(properties); Binder binder = new Binder(propertySource); diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java index bed79127..aa0aca4f 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java @@ -32,6 +32,12 @@ /** * {@link ConfigurationMetadata} Reader + *

Example Usage

+ *
{@code
+ * ConfigurationMetadataReader reader = new ConfigurationMetadataReader();
+ * reader.setResourceLoader(resourceLoader); // Optional, will use default if not set
+ * ConfigurationMetadata metadata = reader.read();
+ * }
* * @author Mercy * @since 1.0.0 diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/source/util/ConfigurationPropertyUtils.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/source/util/ConfigurationPropertyUtils.java index 7d09bdf5..517be5ad 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/source/util/ConfigurationPropertyUtils.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/source/util/ConfigurationPropertyUtils.java @@ -28,6 +28,7 @@ * The utilities class of {@link ConfigurationProperty} * * @author Mercy + * @see ConfigurationProperty * @since 1.0.0 */ public abstract class ConfigurationPropertyUtils { @@ -35,9 +36,21 @@ public abstract class ConfigurationPropertyUtils { /** * Get the prefix of the specified {@link ConfigurationPropertyName} * + *

Example Usage

+ *
{@code
+     * ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
+     * BindContext context = ...; // assume depth = 0
+     * String prefix = getPrefix(name, context); // returns "server.port"
+     *
+     * ConfigurationPropertyName name2 = ConfigurationPropertyName.of("spring.datasource.url");
+     * BindContext context2 = ...; // assume depth = 1
+     * String prefix2 = getPrefix(name2, context2); // returns "spring.datasource"
+     * }
+ * * @param name the {@link ConfigurationPropertyName} * @param context the {@link BindContext} * @return the prefix of the specified {@link ConfigurationPropertyName} + * @throws IllegalArgumentException if name or context is null */ public static final String getPrefix(ConfigurationPropertyName name, BindContext context) { int depth = context.getDepth(); @@ -52,6 +65,15 @@ public static final String getPrefix(ConfigurationPropertyName name, BindContext /** * Return the specified Java Bean property name in dashed form. * + *

Example Usage

+ *
{@code
+     * String result1 = toDashedForm("userName");     // returns "user-name"
+     * String result2 = toDashedForm("firstName");    // returns "first-name"
+     * String result3 = toDashedForm("URL");          // returns "url"
+     * String result4 = toDashedForm("myURL");        // returns "my-url"
+     * String result5 = toDashedForm("user_name");    // returns "user-name"
+     * }
+ * * @param name the source name * @return the dashed from * @see org.springframework.boot.context.properties.bind.DataObjectPropertyName#toDashedForm(String) @@ -62,4 +84,4 @@ public static String toDashedForm(String name) { private ConfigurationPropertyUtils() { } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/util/ConfigurationPropertiesUtils.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/util/ConfigurationPropertiesUtils.java index 43f55aff..664d3bd9 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/util/ConfigurationPropertiesUtils.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/util/ConfigurationPropertiesUtils.java @@ -37,10 +37,38 @@ public abstract class ConfigurationPropertiesUtils { public static final Class CONFIGURATION_PROPERTIES_CLASS = ConfigurationProperties.class; /** - * Find an annotation of {@link ConfigurationProperties} from the specified {@link Bindable} + * Find an annotation of {@link ConfigurationProperties} from the specified {@link Bindable}. + * + *

Example Usage

+ *
{@code
+     * @ConfigurationProperties(prefix = "app.config")
+     * public class AppConfig {
+     *     private String name;
+     *     // getters and setters
+     * }
+     *
+     * Bindable bindable = Bindable.of(AppConfig.class);
+     * ConfigurationProperties props = ConfigurationPropertiesUtils.findConfigurationProperties(bindable);
+     * // props will contain the annotation with prefix "app.config"
+     * }
+ * + *

Another example with nested properties

+ *
{@code
+     * public class ParentConfig {
+     *     @ConfigurationProperties(prefix = "parent.child")
+     *     private ChildConfig child;
+     *     // getters and setters
+     * }
+     *
+     * Bindable bindable = Bindable.of(ChildConfig.class);
+     * ConfigurationProperties props = ConfigurationPropertiesUtils.findConfigurationProperties(bindable);
+     * // props will contain the annotation with prefix "parent.child"
+     * }
* * @param bindable {@link Bindable} * @return an annotation of {@link ConfigurationProperties} if present + * @throws NullPointerException if bindable is null + * @since 1.0.0 */ public static ConfigurationProperties findConfigurationProperties(Bindable bindable) { // Find an annotation of @ConfigurationProperties from annotations diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java index e76e9abf..f67a470c 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionDiagnosisListener.java @@ -27,7 +27,32 @@ import static io.microsphere.spring.boot.util.SpringApplicationUtils.getResourceLoader; /** - * Artifacts Collision diagnosis listener + * {@link ApplicationListener} to detect and diagnose artifacts collision in the application classpath. + *

+ * This listener will be triggered when {@link ApplicationContextInitializedEvent} is published, + * and it will scan all artifacts in the classpath to detect if there are any duplicate artifacts + * (same group ID and artifact ID) existing. + * + *

Example Usage

+ *

+ * To enable this diagnosis, set the property: + *

+ * microsphere.spring.boot.artifacts-collision.enabled=true
+ * 
+ *

+ * Example configuration in application.properties: + *

+ * microsphere.spring.boot.artifacts-collision.enabled=true
+ * 
+ *

+ * Example configuration in application.yml: + *

+ * microsphere:
+ *   spring:
+ *     boot:
+ *       artifacts-collision:
+ *         enabled: true
+ * 
* * @author Mercy * @since 1.0.0 diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionException.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionException.java index f4450ddf..58bfbe73 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionException.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionException.java @@ -20,4 +20,4 @@ public ArtifactsCollisionException(String message, Set artifacts) { public Set getArtifacts() { return artifacts; } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionFailureAnalyzer.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionFailureAnalyzer.java index ba854b51..2730e341 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionFailureAnalyzer.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionFailureAnalyzer.java @@ -34,4 +34,4 @@ private String buildAction(ArtifactsCollisionException cause) { return actionBuilder.toString(); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java index 31578607..d0efc8f9 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListener.java @@ -29,11 +29,46 @@ import static org.springframework.core.io.support.SpringFactoriesLoader.loadFactories; /** - * Listable {@link ApplicationEnvironmentPreparedEvent} {@link ApplicationListener} Class - * {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties"} + * {@link ApplicationListener} implementation that handles {@link ApplicationEnvironmentPreparedEvent} + * to process and merge default properties from various sources into Spring Boot application environment. * - * @author Mercy - * @see SpringApplication#setDefaultProperties(Properties) + *

This listener works at {@link ApplicationEnvironmentPreparedEvent} phase, which occurs after the + * {@link org.springframework.core.env.Environment} is prepared but before the application context + * is created. It collects default properties from multiple sources including:

+ * + *
    + *
  • {@link DefaultPropertiesPostProcessor} implementations loaded via Spring Factories mechanism
  • + *
  • Resources specified through {@link io.microsphere.spring.boot.util.SpringApplicationUtils#getDefaultPropertiesResources()}
  • + *
+ * + *

Example Usage

+ *

Example usage in a custom {@link DefaultPropertiesPostProcessor}:

+ * + *
{@code
+ * public class CustomDefaultPropertiesPostProcessor implements DefaultPropertiesPostProcessor {
+ *
+ *     @Override
+ *     public void initializeResources(Set defaultPropertiesResources) {
+ *         defaultPropertiesResources.add("classpath*:META-INF/custom-default.properties");
+ *     }
+ *
+ *     @Override
+ *     public void postProcess(Map defaultProperties) {
+ *         // Add or modify default properties
+ *         defaultProperties.put("custom.property", "defaultValue");
+ *     }
+ * }
+ * }
+ * + *

Register the processor in META-INF/spring.factories:

+ * + *
{@code
+ * io.microsphere.spring.boot.env.DefaultPropertiesPostProcessor=\
+ * com.example.CustomDefaultPropertiesPostProcessor
+ * }
+ * + * @author
Mercy + * @see SpringApplication#setDefaultProperties * @see DefaultPropertiesPostProcessor * @since 1.0.0 */ diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesPostProcessor.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesPostProcessor.java index e82614b4..0768c18e 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesPostProcessor.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesPostProcessor.java @@ -8,7 +8,33 @@ import java.util.Set; /** - * {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties"} Post Processor + * {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties"} Post Processor. + * + *

Example Usage

+ *

Example usage in a custom {@link DefaultPropertiesPostProcessor}:

+ * + *
{@code
+ * public class CustomDefaultPropertiesPostProcessor implements DefaultPropertiesPostProcessor {
+ *
+ *     @Override
+ *     public void initializeResources(Set defaultPropertiesResources) {
+ *         defaultPropertiesResources.add("classpath*:META-INF/custom-default.properties");
+ *     }
+ *
+ *     @Override
+ *     public void postProcess(Map defaultProperties) {
+ *         // Add or modify default properties
+ *         defaultProperties.put("custom.property", "defaultValue");
+ *     }
+ * }
+ * }
+ * + *

Register the processor in META-INF/spring.factories:

+ * + *
{@code
+ * io.microsphere.spring.boot.env.DefaultPropertiesPostProcessor=\
+ * com.example.CustomDefaultPropertiesPostProcessor
+ * }
* * @author Mercy * @see DefaultPropertiesApplicationListener diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/PropertySourceLoaders.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/PropertySourceLoaders.java index 4102abd1..04c76e7d 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/PropertySourceLoaders.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/PropertySourceLoaders.java @@ -39,6 +39,26 @@ /** * The composite class of {@link PropertySourceLoader} with utilities features + *

+ * This class loads property sources from various file formats by delegating to individual + * {@link PropertySourceLoader} implementations. It supports all file extensions that are + * supported by the loaded factories. + * + *

Example Usage

+ *
{@code
+ * // Create a new PropertySourceLoaders instance
+ * PropertySourceLoaders loaders = new PropertySourceLoaders();
+ *
+ * // Get supported file extensions
+ * String[] extensions = loaders.getFileExtensions();
+ *
+ * // Load property sources from a resource
+ * Resource resource = new ClassPathResource("application.properties");
+ * List> propertySources = loaders.load("myProperties", resource);
+ *
+ * // Reload a property source with origin tracking
+ * PropertySource trackedSource = loaders.reloadAsOriginTracked(propertySources.get(0));
+ * }
* * @author
Mercy * @see PropertySourceLoader diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java index 44efe6ef..d2155209 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepository.java @@ -135,4 +135,4 @@ private Map createNamedItems(List items, Ite }); return namedItems; } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/FailureReportSpringApplicationRunListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/FailureReportSpringApplicationRunListener.java index ba918c2a..7829dd1b 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/FailureReportSpringApplicationRunListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/FailureReportSpringApplicationRunListener.java @@ -24,4 +24,4 @@ public void failed(ConfigurableApplicationContext context, Throwable exception) err.print("The Spring Boot application fails to start. The causes are as follows:"); exception.printStackTrace(err); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/LoggingSpringApplicationRunListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/LoggingSpringApplicationRunListener.java index e3b7a857..c5b0326d 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/LoggingSpringApplicationRunListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/LoggingSpringApplicationRunListener.java @@ -91,4 +91,4 @@ public void failed(ConfigurableApplicationContext context, Throwable exception) super.failed(context, exception); log(getSpringApplication(), getArgs(), context, "failed : {}", exception); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/SpringApplicationRunListenerAdapter.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/SpringApplicationRunListenerAdapter.java index 1e612e2e..972ea979 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/SpringApplicationRunListenerAdapter.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/SpringApplicationRunListenerAdapter.java @@ -67,4 +67,4 @@ public final void setOrder(int order) { public final int getOrder() { return order; } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportInitializer.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportInitializer.java index 1046da02..3f0b5e62 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportInitializer.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportInitializer.java @@ -16,4 +16,4 @@ public class ConditionEvaluationReportInitializer implements ApplicationContextI public void initialize(ConfigurableApplicationContext applicationContext) { applicationContext.addBeanFactoryPostProcessor(ConditionEvaluationReportBuilder::build); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportListener.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportListener.java index 0063e3eb..7415c607 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportListener.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportListener.java @@ -26,4 +26,4 @@ protected void reportConditions(ConfigurableApplicationContext context) { ConditionsReportMessageBuilder messageBuilder = new ConditionsReportMessageBuilder(context); messageBuilder.build().forEach(logger::info); } -} +} \ No newline at end of file diff --git a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationSpringBootExceptionReporter.java b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationSpringBootExceptionReporter.java index 4a21eea9..7f60a285 100644 --- a/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationSpringBootExceptionReporter.java +++ b/microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationSpringBootExceptionReporter.java @@ -35,4 +35,4 @@ protected void reportConditions(ConfigurableApplicationContext context) { ConditionsReportMessageBuilder messageBuilder = new ConditionsReportMessageBuilder(context); messageBuilder.build().forEach(logger::error); } -} +} \ No newline at end of file