├── microsphere-spring-boot-core ├── src │ ├── test │ │ ├── resources │ │ │ ├── META-INF │ │ │ │ ├── config │ │ │ │ │ └── default │ │ │ │ │ │ ├── test.properties │ │ │ │ │ │ └── test.yaml │ │ │ │ ├── services │ │ │ │ │ └── io.microsphere.classloading.ArtifactResourceResolver │ │ │ │ └── spring.factories │ │ │ └── logback-test.xml │ │ └── java │ │ │ ├── org │ │ │ └── springframework │ │ │ │ └── cloud │ │ │ │ └── bootstrap │ │ │ │ └── BootstrapApplicationListener.java │ │ │ └── io │ │ │ └── microsphere │ │ │ └── spring │ │ │ └── boot │ │ │ ├── domain │ │ │ └── User.java │ │ │ ├── report │ │ │ ├── ConditionEvaluationReportBuilderTest.java │ │ │ ├── ConditionEvaluationReportListenerTest.java │ │ │ ├── ConditionsReportMessageBuilderTest.java │ │ │ └── ConditionEvaluationSpringBootExceptionReporterTest.java │ │ │ ├── diagnostics │ │ │ ├── ArtifactsCollisionExceptionTest.java │ │ │ ├── ArtifactsCollisionFailureAnalyzerTest.java │ │ │ └── ArtifactsCollisionResourceResolver.java │ │ │ ├── context │ │ │ ├── AbstractApplicationPreparedEventTest.java │ │ │ ├── properties │ │ │ │ ├── bind │ │ │ │ │ ├── util │ │ │ │ │ │ └── BindHandlerUtilsTest.java │ │ │ │ │ └── BindListenerTest.java │ │ │ │ ├── util │ │ │ │ │ └── ConfigurationPropertiesUtilsTest.java │ │ │ │ ├── source │ │ │ │ │ └── util │ │ │ │ │ │ └── ConfigurationPropertyUtilsTest.java │ │ │ │ ├── metadata │ │ │ │ │ └── ConfigurationMetadataReaderTest.java │ │ │ │ └── ConfigurationPropertiesBeanInfoTest.java │ │ │ ├── LoggingOnceApplicationPreparedEventListenerTest.java │ │ │ └── config │ │ │ │ └── BindableConfigurationBeanBinderTest.java │ │ │ ├── constants │ │ │ ├── PropertyConstantsTest.java │ │ │ └── SpringBootPropertyConstantsTest.java │ │ │ ├── env │ │ │ ├── PropertiesEmptyPropertySourceLoader.java │ │ │ ├── DefaultPropertiesPostProcessorTest.java │ │ │ ├── config │ │ │ │ └── metadata │ │ │ │ │ └── ConfigurationMetadataRepositoryTest.java │ │ │ └── DefaultPropertiesApplicationListenerTest.java │ │ │ ├── util │ │ │ └── TestUtils.java │ │ │ ├── autoconfigure │ │ │ └── ApplicationAutoConfigurationTest.java │ │ │ ├── listener │ │ │ └── LoggingSpringApplicationRunListenerTest.java │ │ │ ├── classloading │ │ │ └── BannedArtifactClassLoadingListenerTest.java │ │ │ └── condition │ │ │ └── OnPropertyPrefixConditionTest.java │ └── main │ │ ├── resources │ │ ├── config │ │ │ └── default │ │ │ │ └── core.properties │ │ └── META-INF │ │ │ └── spring.factories │ │ └── java │ │ └── io │ │ └── microsphere │ │ └── spring │ │ └── boot │ │ ├── diagnostics │ │ ├── ArtifactsCollisionException.java │ │ └── ArtifactsCollisionFailureAnalyzer.java │ │ ├── report │ │ ├── ConditionEvaluationReportInitializer.java │ │ ├── ConditionEvaluationReportListener.java │ │ ├── ConditionEvaluationSpringBootExceptionReporter.java │ │ └── ConditionEvaluationReportBuilder.java │ │ ├── listener │ │ ├── FailureReportSpringApplicationRunListener.java │ │ ├── SpringApplicationRunListenerAdapter.java │ │ └── LoggingSpringApplicationRunListener.java │ │ ├── constants │ │ ├── SpringBootPropertyConstants.java │ │ └── PropertyConstants.java │ │ ├── context │ │ ├── LoggingOnceMainApplicationPreparedEventListener.java │ │ ├── properties │ │ │ ├── bind │ │ │ │ ├── ConfigurationPropertiesBeanPropertyChangedEvent.java │ │ │ │ ├── BindListeners.java │ │ │ │ ├── util │ │ │ │ │ └── BindHandlerUtils.java │ │ │ │ ├── ListenableBindHandlerAdapter.java │ │ │ │ └── BindListener.java │ │ │ ├── ListenableConfigurationPropertiesBindHandlerAdvisor.java │ │ │ ├── source │ │ │ │ └── util │ │ │ │ │ └── ConfigurationPropertyUtils.java │ │ │ ├── util │ │ │ │ └── ConfigurationPropertiesUtils.java │ │ │ └── metadata │ │ │ │ └── ConfigurationMetadataReader.java │ │ ├── LoggingOnceApplicationPreparedEventListener.java │ │ ├── config │ │ │ └── BindableConfigurationBeanBinder.java │ │ ├── OnceMainApplicationPreparedEventListener.java │ │ └── OnceApplicationPreparedEventListener.java │ │ ├── env │ │ ├── SpringApplicationDefaultPropertiesPostProcessor.java │ │ └── DefaultPropertiesPostProcessor.java │ │ └── condition │ │ ├── ConditionalOnPropertyPrefix.java │ │ └── OnPropertyPrefixCondition.java └── pom.xml ├── microsphere-spring-boot-actuator ├── src │ ├── test │ │ ├── resources │ │ │ ├── application.properties │ │ │ └── logback-test.xml │ │ └── java │ │ │ └── io │ │ │ └── microsphere │ │ │ └── spring │ │ │ └── boot │ │ │ └── actuate │ │ │ ├── constants │ │ │ └── PropertyConstantsTest.java │ │ │ ├── autoconfigure │ │ │ ├── ActuatorAutoConfigurationTest.java │ │ │ └── ActuatorEndpointsAutoConfigurationTest.java │ │ │ └── env │ │ │ └── DefaultPropertiesTest.java │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ ├── services │ │ │ └── io.microsphere.metadata.ConfigurationPropertyLoader │ │ │ ├── spring │ │ │ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports │ │ │ └── spring.factories │ │ └── java │ │ └── io │ │ └── microsphere │ │ └── spring │ │ └── boot │ │ └── actuate │ │ ├── endpoint │ │ ├── ArtifactsEndpoint.java │ │ ├── ConfigurationMetadataEndpoint.java │ │ └── WebEndpoints.java │ │ ├── constants │ │ └── PropertyConstants.java │ │ ├── condition │ │ └── ConditionalOnConfigurationProcessorPresent.java │ │ └── MonitoredThreadPoolTaskScheduler.java └── pom.xml ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .gitignore ├── microsphere-spring-boot-dependencies └── pom.xml ├── .github └── workflows │ ├── maven-build.yml │ └── maven-publish.yml ├── pom.xml ├── CODE_OF_CONDUCT.md └── microsphere-spring-boot-parent └── pom.xml /microsphere-spring-boot-core/src/test/resources/META-INF/config/default/test.properties: -------------------------------------------------------------------------------- 1 | test.name = test -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/resources/META-INF/config/default/test.yaml: -------------------------------------------------------------------------------- 1 | test: 2 | name: Test -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/test/resources/application.properties: -------------------------------------------------------------------------------- 1 | management.endpoint.loggers.enabled = false -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsphere-projects/microsphere-spring-boot/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/resources/META-INF/services/io.microsphere.metadata.ConfigurationPropertyLoader: -------------------------------------------------------------------------------- 1 | io.microsphere.metadata.MetadataResourceConfigurationPropertyLoader -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/resources/META-INF/services/io.microsphere.classloading.ArtifactResourceResolver: -------------------------------------------------------------------------------- 1 | io.microsphere.spring.boot.diagnostics.ArtifactsCollisionResourceResolver -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports: -------------------------------------------------------------------------------- 1 | io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration 2 | io.microsphere.spring.boot.actuate.autoconfigure.ActuatorEndpointsAutoConfiguration -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | io.microsphere.spring.boot.actuate.autoconfigure.ActuatorAutoConfiguration,\ 3 | io.microsphere.spring.boot.actuate.autoconfigure.ActuatorEndpointsAutoConfiguration -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/resources/config/default/core.properties: -------------------------------------------------------------------------------- 1 | ## Spring Boot Default Properties 2 | 3 | ### Spring Boot Graceful Shutdown 4 | server.shutdown = graceful 5 | spring.lifecycle.timeout-per-shutdown-phase = 60s 6 | 7 | ### Disabled Spring Boot Built-in Filter 8 | spring.mvc.hiddenmethod.filter.enabled = false 9 | spring.mvc.formcontent.filter.enabled = false 10 | spring.mvc.favicon.enabled = false 11 | 12 | 13 | ## Microsphere Spring Boot Default Properties 14 | 15 | ### Exclude Spring Boot Built-in Auto-Configuration Class 16 | microsphere.autoconfigure.exclude=\ 17 | org.springframework.boot.actuate.autoconfigure.metrics.web.servlet.WebMvcMetricsAutoConfiguration -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionException.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.diagnostics; 2 | 3 | import java.util.Set; 4 | 5 | /** 6 | * Artifacts Collision {@link RuntimeException} 7 | * 8 | * @author Mercy 9 | * @since 1.0.0 10 | */ 11 | public class ArtifactsCollisionException extends RuntimeException { 12 | 13 | private final Set artifacts; 14 | 15 | public ArtifactsCollisionException(String message, Set artifacts) { 16 | super(message); 17 | this.artifacts = artifacts; 18 | } 19 | 20 | public Set getArtifacts() { 21 | return artifacts; 22 | } 23 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${ENCODER_PATTERN} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ${ENCODER_PATTERN} 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportInitializer.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.report; 2 | 3 | import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | 7 | /** 8 | * {@link ConditionEvaluationReport} initializer 9 | * 10 | * @author Mercy 11 | * @since 1.0.0 12 | */ 13 | public class ConditionEvaluationReportInitializer implements ApplicationContextInitializer { 14 | 15 | @Override 16 | public void initialize(ConfigurableApplicationContext applicationContext) { 17 | applicationContext.addBeanFactoryPostProcessor(ConditionEvaluationReportBuilder::build); 18 | } 19 | } -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Copyright 2013-2023 the original author or authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.0/apache-maven-3.9.0-bin.zip 16 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # ApplicationContextInitializer 2 | org.springframework.context.ApplicationContextInitializer=\ 3 | io.microsphere.spring.context.event.EventPublishingBeanInitializer 4 | 5 | # PropertySourceLoader 6 | org.springframework.boot.env.PropertySourceLoader=\ 7 | io.microsphere.spring.boot.env.PropertiesEmptyPropertySourceLoader 8 | 9 | # BeanListener 10 | io.microsphere.spring.context.event.BeanListener=\ 11 | io.microsphere.spring.context.event.LoggingBeanListener,\ 12 | io.microsphere.spring.context.event.BeanTimeStatistics 13 | 14 | # BeanFactoryListener 15 | io.microsphere.spring.context.event.BeanFactoryListener=\ 16 | io.microsphere.spring.context.event.LoggingBeanFactoryListener 17 | 18 | # ApplicationListener 19 | org.springframework.context.ApplicationListener=\ 20 | io.microsphere.spring.boot.context.LoggingOnceApplicationPreparedEventListener,\ 21 | io.microsphere.spring.boot.context.LoggingOnceMainApplicationPreparedEventListener -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | 25 | # maven ignore 26 | target/ 27 | !.mvn/wrapper/* 28 | 29 | # eclipse ignore 30 | .settings/ 31 | .project 32 | .classpath 33 | 34 | # idea ignore 35 | .idea/ 36 | .idea 37 | *.ipr 38 | *.iml 39 | *.iws 40 | 41 | # temp ignore 42 | *.log 43 | *.cache 44 | *.diff 45 | *.patch 46 | *.tmp 47 | 48 | # system ignore 49 | .DS_Store 50 | Thumbs.db 51 | *.orig 52 | 53 | # flatten ignore 54 | .flattened-pom.xml 55 | 56 | # license check result 57 | license-list 58 | 59 | # grpc compiler 60 | compiler/gradle.properties 61 | compiler/build/* 62 | compiler/.gradle/* 63 | 64 | # Tomcat 65 | .extract 66 | .java-version 67 | 68 | # vscode 69 | .vscode/ 70 | 71 | # others 72 | build.txt -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ArtifactsEndpoint.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.actuate.endpoint; 2 | 3 | import io.microsphere.classloading.Artifact; 4 | import io.microsphere.classloading.ArtifactDetector; 5 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint; 6 | import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * {@link Artifact Artifacts} {@link Endpoint @Endpoint} 12 | * 13 | * @author Mercy 14 | * @see Artifact 15 | * @see Endpoint 16 | * @since 1.0.0 17 | */ 18 | @Endpoint(id = "artifacts") 19 | public class ArtifactsEndpoint { 20 | 21 | private final ArtifactDetector artifactDetector; 22 | 23 | public ArtifactsEndpoint(ClassLoader classLoader) { 24 | this.artifactDetector = new ArtifactDetector(classLoader); 25 | } 26 | 27 | @ReadOperation 28 | public List getArtifactMetaInfoList() { 29 | return artifactDetector.detect(false); 30 | } 31 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/FailureReportSpringApplicationRunListener.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.listener; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.SpringApplicationRunListener; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | 7 | import java.io.PrintStream; 8 | 9 | /** 10 | * {@link SpringApplicationRunListener} Failure Report 11 | * 12 | * @author Mercy 13 | * @since 1.0.0 14 | */ 15 | public class FailureReportSpringApplicationRunListener extends SpringApplicationRunListenerAdapter { 16 | 17 | public FailureReportSpringApplicationRunListener(SpringApplication springApplication, String[] args) { 18 | super(springApplication, args); 19 | } 20 | 21 | @Override 22 | public void failed(ConfigurableApplicationContext context, Throwable exception) { 23 | PrintStream err = System.err; 24 | err.print("The Spring Boot application fails to start. The causes are as follows:"); 25 | exception.printStackTrace(err); 26 | } 27 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportListener.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.report; 2 | 3 | import io.microsphere.logging.Logger; 4 | import org.springframework.boot.context.event.ApplicationReadyEvent; 5 | import org.springframework.context.ApplicationListener; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | 8 | import static io.microsphere.logging.LoggerFactory.getLogger; 9 | 10 | /** 11 | * Spring Boot Conditions Evaluation report listener 12 | * 13 | * @author Mercy 14 | * @since 1.0.0 15 | */ 16 | public class ConditionEvaluationReportListener implements ApplicationListener { 17 | 18 | private static final Logger logger = getLogger(ConditionEvaluationReportListener.class); 19 | 20 | @Override 21 | public void onApplicationEvent(ApplicationReadyEvent event) { 22 | reportConditions(event.getApplicationContext()); 23 | } 24 | 25 | protected void reportConditions(ConfigurableApplicationContext context) { 26 | ConditionsReportMessageBuilder messageBuilder = new ConditionsReportMessageBuilder(context); 27 | messageBuilder.build().forEach(logger::info); 28 | } 29 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package org.springframework.cloud.bootstrap; 19 | 20 | import io.microsphere.spring.boot.context.OnceMainApplicationPreparedEventListener; 21 | 22 | /** 23 | * Empty class only for testing 24 | * 25 | * @author Mercy 26 | * @see OnceMainApplicationPreparedEventListener 27 | * @since 1.0.0 28 | */ 29 | public class BootstrapApplicationListener { 30 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/SpringBootPropertyConstants.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.constants; 2 | 3 | import org.springframework.boot.autoconfigure.AutoConfigurationImportSelector; 4 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 5 | import org.springframework.boot.context.properties.source.ConfigurationPropertySources; 6 | import org.springframework.core.env.Environment; 7 | import org.springframework.core.env.PropertySource; 8 | 9 | /** 10 | * The Constants for Spring Boot Property 11 | * 12 | * @author Mercy 13 | * @since 1.0.0 14 | */ 15 | public interface SpringBootPropertyConstants { 16 | 17 | /** 18 | * The property name to exclude the class names of Spring Boot Auto-Configuration 19 | * 20 | * @see EnableAutoConfiguration 21 | * @see AutoConfigurationImportSelector#PROPERTY_NAME_AUTOCONFIGURE_EXCLUDE 22 | */ 23 | String SPRING_AUTO_CONFIGURE_EXCLUDE_PROPERTY_NAME = "spring.autoconfigure.exclude"; 24 | 25 | /** 26 | * The name of the {@link PropertySource} {@link #attach(Environment) adapter} since Spring Boot 2 27 | * 28 | * @see ConfigurationPropertySources#ATTACHED_PROPERTY_SOURCE_NAME 29 | */ 30 | String ATTACHED_PROPERTY_SOURCE_NAME = "configurationProperties"; 31 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/domain/User.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.domain; 18 | 19 | /** 20 | * User Domain Class 21 | * 22 | * @author Mercy 23 | * @since 1.0.0 24 | */ 25 | public class User { 26 | 27 | private String name; 28 | 29 | private Integer age; 30 | 31 | public String getName() { 32 | return name; 33 | } 34 | 35 | public void setName(String name) { 36 | this.name = name; 37 | } 38 | 39 | public Integer getAge() { 40 | return age; 41 | } 42 | 43 | public void setAge(Integer age) { 44 | this.age = age; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationSpringBootExceptionReporter.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.report; 2 | 3 | import io.microsphere.logging.Logger; 4 | import org.springframework.boot.SpringBootExceptionReporter; 5 | import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | 8 | import static io.microsphere.logging.LoggerFactory.getLogger; 9 | 10 | /** 11 | * Spring Boot Conditions {@link SpringBootExceptionReporter} 12 | * 13 | * @author Mercy 14 | * @see ConditionEvaluationReport 15 | * @since 1.0.0 16 | */ 17 | public class ConditionEvaluationSpringBootExceptionReporter implements SpringBootExceptionReporter { 18 | 19 | private static final Logger logger = getLogger(ConditionEvaluationSpringBootExceptionReporter.class); 20 | 21 | private final ConfigurableApplicationContext context; 22 | 23 | public ConditionEvaluationSpringBootExceptionReporter(ConfigurableApplicationContext context) { 24 | this.context = context; 25 | } 26 | 27 | @Override 28 | public boolean reportException(Throwable failure) { 29 | logger.error("Spring Boot fails to start!", failure); 30 | reportConditions(context); 31 | return false; 32 | } 33 | 34 | protected void reportConditions(ConfigurableApplicationContext context) { 35 | ConditionsReportMessageBuilder messageBuilder = new ConditionsReportMessageBuilder(context); 36 | messageBuilder.build().forEach(logger::error); 37 | } 38 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/report/ConditionEvaluationReportBuilderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.report; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static io.microsphere.spring.boot.report.ConditionEvaluationReportBuilder.getBeanFactoryId; 24 | import static org.junit.jupiter.api.Assertions.assertEquals; 25 | 26 | /** 27 | * {@link ConditionEvaluationReportBuilder} Test 28 | * 29 | * @author Mercy 30 | * @see ConditionEvaluationReportBuilder 31 | * @since 1.0.0 32 | */ 33 | class ConditionEvaluationReportBuilderTest { 34 | 35 | @Test 36 | void testGetBeanFactoryIdWithNullBeanFactory() { 37 | assertEquals("", getBeanFactoryId(null)); 38 | } 39 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-dependencies/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | io.github.microsphere-projects 7 | microsphere-spring-boot-parent 8 | ${revision} 9 | ../microsphere-spring-boot-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | io.github.microsphere-projects 14 | microsphere-spring-boot-dependencies 15 | ${revision} 16 | pom 17 | 18 | Microsphere :: Spring Boot :: Dependencies 19 | Microsphere Spring Boot Dependencies 20 | 21 | 22 | 23 | 24 | 25 | io.github.microsphere-projects 26 | microsphere-spring-boot-core 27 | ${revision} 28 | 29 | 30 | 31 | io.github.microsphere-projects 32 | microsphere-spring-boot-actuator 33 | ${revision} 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionFailureAnalyzer.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.diagnostics; 2 | 3 | import org.springframework.boot.diagnostics.AbstractFailureAnalyzer; 4 | import org.springframework.boot.diagnostics.FailureAnalysis; 5 | import org.springframework.boot.diagnostics.FailureAnalyzer; 6 | 7 | import java.util.Set; 8 | 9 | import static java.lang.System.lineSeparator; 10 | 11 | /** 12 | * Artifacts Collision {@link FailureAnalyzer} Class 13 | * 14 | * @author Mercy 15 | * @since 1.0.0 16 | */ 17 | public class ArtifactsCollisionFailureAnalyzer extends AbstractFailureAnalyzer { 18 | 19 | @Override 20 | protected FailureAnalysis analyze(Throwable rootFailure, ArtifactsCollisionException cause) { 21 | return new FailureAnalysis(cause.getMessage(), buildAction(cause), cause); 22 | } 23 | 24 | private String buildAction(ArtifactsCollisionException cause) { 25 | Set artifacts = cause.getArtifacts(); 26 | StringBuilder actionBuilder = new StringBuilder("Analyze conflict Artifacts by running the following Maven command in the root directory of the project source code:") 27 | .append(lineSeparator()) 28 | .append("mvn dependency:tree -Dincludes="); 29 | for (String artifact : artifacts) { 30 | actionBuilder.append(artifact).append(","); 31 | } 32 | 33 | actionBuilder.append(lineSeparator()).append("After analyzing the results, exclude them in the pom.xml file one by one!"); 34 | 35 | return actionBuilder.toString(); 36 | } 37 | } -------------------------------------------------------------------------------- /.github/workflows/maven-build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Maven Build 10 | 11 | on: 12 | push: 13 | branches: [ 'dev' ] 14 | pull_request: 15 | branches: [ 'main', 'dev' , 'release' ] 16 | 17 | jobs: 18 | build: 19 | runs-on: ubuntu-latest 20 | strategy: 21 | matrix: 22 | java: [ '17' , '21' , '25' ] 23 | maven-profile-spring-boot: [ 'spring-boot-3.0' , 'spring-boot-3.1' , 'spring-boot-3.2' , 24 | 'spring-boot-3.3' , 'spring-boot-3.4' 25 | ] 26 | steps: 27 | - name: Checkout Source 28 | uses: actions/checkout@v4 29 | 30 | - name: Setup JDK ${{ matrix.Java }} 31 | uses: actions/setup-java@v4 32 | with: 33 | distribution: 'temurin' 34 | java-version: ${{ matrix.java }} 35 | cache: maven 36 | 37 | - name: Build with Maven 38 | run: mvn 39 | --batch-mode 40 | --update-snapshots 41 | --file pom.xml 42 | -Drevision=0.0.1-SNAPSHOT 43 | -Dsurefire.useSystemClassLoader=false 44 | test 45 | --activate-profiles test,coverage,${{ matrix.maven-profile-spring-boot }} 46 | 47 | - name: Upload coverage reports to Codecov 48 | uses: codecov/codecov-action@v5 49 | with: 50 | token: ${{ secrets.CODECOV_TOKEN }} 51 | slug: microsphere-projects/microsphere-spring-boot -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | # ApplicationContextInitializer 2 | org.springframework.context.ApplicationContextInitializer=\ 3 | io.microsphere.spring.context.event.EventPublishingBeanInitializer,\ 4 | io.microsphere.spring.boot.report.ConditionEvaluationReportInitializer,\ 5 | io.microsphere.spring.beans.factory.support.ListenableAutowireCandidateResolverInitializer,\ 6 | io.microsphere.spring.core.env.ListenableConfigurableEnvironmentInitializer,\ 7 | io.microsphere.spring.boot.env.config.OriginTrackedConfigurationPropertyInitializer 8 | 9 | # SpringApplicationRunListener 10 | org.springframework.boot.SpringApplicationRunListener=\ 11 | io.microsphere.spring.boot.classloading.BannedArtifactClassLoadingListener,\ 12 | io.microsphere.spring.boot.listener.FailureReportSpringApplicationRunListener 13 | 14 | # Application Listeners 15 | org.springframework.context.ApplicationListener=\ 16 | io.microsphere.spring.boot.diagnostics.ArtifactsCollisionDiagnosisListener,\ 17 | io.microsphere.spring.boot.report.ConditionEvaluationReportListener,\ 18 | io.microsphere.spring.boot.env.DefaultPropertiesApplicationListener 19 | 20 | # SpringBootExceptionReporter 21 | org.springframework.boot.SpringBootExceptionReporter=\ 22 | io.microsphere.spring.boot.report.ConditionEvaluationSpringBootExceptionReporter 23 | 24 | # Failure Analyzers 25 | org.springframework.boot.diagnostics.FailureAnalyzer=\ 26 | io.microsphere.spring.boot.diagnostics.ArtifactsCollisionFailureAnalyzer 27 | 28 | # AutoConfigurationImportFilter 29 | org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\ 30 | io.microsphere.spring.boot.autoconfigure.ConfigurableAutoConfigurationImportFilter 31 | 32 | # DefaultPropertiesPostProcessor 33 | io.microsphere.spring.boot.env.DefaultPropertiesPostProcessor=\ 34 | io.microsphere.spring.boot.env.SpringApplicationDefaultPropertiesPostProcessor 35 | 36 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionExceptionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.diagnostics; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | 23 | import java.util.Set; 24 | 25 | import static io.microsphere.collection.Sets.ofSet; 26 | import static org.junit.jupiter.api.Assertions.assertInstanceOf; 27 | import static org.junit.jupiter.api.Assertions.assertSame; 28 | 29 | /** 30 | * {@link ArtifactsCollisionException} Test 31 | * 32 | * @author Mercy 33 | * @see ArtifactsCollisionException 34 | * @since 1.0.0 35 | */ 36 | class ArtifactsCollisionExceptionTest { 37 | 38 | @Test 39 | void testGetArtifacts() { 40 | Set artifacts = ofSet("a", "b", "c"); 41 | ArtifactsCollisionException exception = new ArtifactsCollisionException("For testing", artifacts); 42 | assertInstanceOf(RuntimeException.class, exception); 43 | assertSame(artifacts, exception.getArtifacts()); 44 | } 45 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/constants/PropertyConstantsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.actuate.constants; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | 23 | import static io.microsphere.spring.boot.actuate.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX; 24 | import static io.microsphere.spring.boot.actuate.constants.PropertyConstants.TASK_SCHEDULER_PROPERTY_NAME_PREFIX; 25 | import static org.junit.jupiter.api.Assertions.assertEquals; 26 | 27 | /** 28 | * {@link PropertyConstants} Test 29 | * 30 | * @author Mercy 31 | * @see PropertyConstants 32 | * @since 1.0.0 33 | */ 34 | class PropertyConstantsTest { 35 | 36 | @Test 37 | void testConstants() { 38 | assertEquals("microsphere.spring.boot.actuator.", MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX); 39 | assertEquals("microsphere.spring.boot.actuator.task-scheduler.", TASK_SCHEDULER_PROPERTY_NAME_PREFIX); 40 | } 41 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/constants/PropertyConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.actuate.constants; 18 | 19 | import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX; 20 | 21 | /** 22 | * The Property constants for Microsphere Spring Boot Actuator 23 | * 24 | * @author Mercy 25 | * @since 1.0.0 26 | */ 27 | public interface PropertyConstants { 28 | 29 | /** 30 | * The property name prefix of Microsphere Spring Boot : "microsphere.spring.boot.actuator." 31 | */ 32 | String MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX + "actuator."; 33 | 34 | /** 35 | * The property name prefix of Microsphere Spring Boot Actuator Task Scheduler : "microsphere.spring.boot.actuator.task-scheduler." 36 | */ 37 | String TASK_SCHEDULER_PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_BOOT_ACTUATOR_PROPERTY_NAME_PREFIX + "task-scheduler."; 38 | } -------------------------------------------------------------------------------- /.github/workflows/maven-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Maven Publish 10 | 11 | on: 12 | push: 13 | branches: [ 'release' ] 14 | workflow_dispatch: 15 | inputs: 16 | revision: 17 | description: 'The version to publish for Spring Boot 3+ and JDK 17+' 18 | required: true 19 | default: '2.0.0-SNAPSHOT' 20 | 21 | jobs: 22 | build: 23 | runs-on: ubuntu-latest 24 | if: ${{ inputs.revision }} 25 | steps: 26 | - name: Checkout Source 27 | uses: actions/checkout@v4 28 | 29 | - name: Setup Maven Central Repository 30 | uses: actions/setup-java@v4 31 | with: 32 | java-version: '17' 33 | distribution: 'temurin' 34 | server-id: ossrh 35 | server-username: MAVEN_USERNAME 36 | server-password: MAVEN_PASSWORD 37 | cache: maven 38 | 39 | - name: Publish package 40 | run: mvn 41 | --batch-mode 42 | --update-snapshots 43 | --file pom.xml 44 | -Drevision=${{ inputs.revision }} 45 | -Dsurefire.useSystemClassLoader=false 46 | -Dgpg.skip=true 47 | deploy 48 | --activate-profiles publish,ci 49 | env: 50 | MAVEN_USERNAME: ${{ secrets.OSS_SONATYPE_USERNAME }} 51 | MAVEN_PASSWORD: ${{ secrets.OSS_SONATYPE_PASSWORD }} 52 | SIGN_KEY_ID: ${{ secrets.OSS_SIGNING_KEY_ID_LONG }} 53 | SIGN_KEY: ${{ secrets.OSS_SIGNING_KEY }} 54 | SIGN_KEY_PASS: ${{ secrets.OSS_SIGNING_PASSWORD }} 55 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/LoggingOnceMainApplicationPreparedEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context; 19 | 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.context.ConfigurableApplicationContext; 22 | 23 | import static io.microsphere.spring.boot.util.SpringApplicationUtils.log; 24 | 25 | /** 26 | * {@link OnceMainApplicationPreparedEventListener} for Logging with specified level 27 | * 28 | * @author Mercy 29 | * @see OnceMainApplicationPreparedEventListener 30 | * @since 1.0.0 31 | */ 32 | public class LoggingOnceMainApplicationPreparedEventListener extends OnceMainApplicationPreparedEventListener { 33 | 34 | public LoggingOnceMainApplicationPreparedEventListener() { 35 | super.setOrder(LOWEST_PRECEDENCE); 36 | } 37 | 38 | @Override 39 | protected void onApplicationEvent(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context) { 40 | log(springApplication, args, context, "onApplicationPreparedEvent"); 41 | } 42 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/AbstractApplicationPreparedEventTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context; 19 | 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 22 | import org.springframework.context.ConfigurableApplicationContext; 23 | 24 | import static io.microsphere.spring.boot.util.TestUtils.application; 25 | import static java.lang.System.nanoTime; 26 | 27 | /** 28 | * Abstract class for {@link ApplicationPreparedEvent} Test 29 | * 30 | * @author Mercy 31 | * @see ApplicationPreparedEvent 32 | * @since 1.0.0 33 | */ 34 | class AbstractApplicationPreparedEventTest { 35 | 36 | protected ApplicationPreparedEvent createEvent(String... args) { 37 | SpringApplication springApplication = application(getClass()); 38 | ConfigurableApplicationContext context = springApplication.run(args); 39 | context.setId("test-context-" + nanoTime()); 40 | return new ApplicationPreparedEvent(springApplication, args, context); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/condition/ConditionalOnConfigurationProcessorPresent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.actuate.condition; 18 | 19 | import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; 20 | import org.springframework.context.annotation.Conditional; 21 | 22 | import java.lang.annotation.Documented; 23 | import java.lang.annotation.Retention; 24 | import java.lang.annotation.Target; 25 | 26 | import static java.lang.annotation.ElementType.METHOD; 27 | import static java.lang.annotation.ElementType.TYPE; 28 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 29 | 30 | /** 31 | * {@link Conditional @Conditional} that checks whether the artifact "org.springframework.boot:spring-boot-configuration-processor" 32 | * is present 33 | * 34 | * @author Mercy 35 | * @see Conditional 36 | * @since 1.0.0 37 | */ 38 | @Target({ TYPE, METHOD }) 39 | @Retention(RUNTIME) 40 | @Documented 41 | @ConditionalOnClass(name = "org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata") 42 | public @interface ConditionalOnConfigurationProcessorPresent { 43 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/constants/PropertyConstantsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.constants; 18 | 19 | import org.junit.jupiter.api.Test; 20 | 21 | import static io.microsphere.spring.boot.constants.PropertyConstants.DEFAULT_MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL; 22 | import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME; 23 | import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX; 24 | import static org.junit.jupiter.api.Assertions.assertEquals; 25 | 26 | /** 27 | * {@link PropertyConstants} Test 28 | * 29 | * @author Mercy 30 | * @see PropertyConstants 31 | * @since 1.0.0 32 | */ 33 | class PropertyConstantsTest { 34 | 35 | @Test 36 | void test() { 37 | assertEquals("microsphere.spring.boot.", MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX); 38 | assertEquals("TRACE", DEFAULT_MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL); 39 | assertEquals("microsphere.spring.boot.logging.level", MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME); 40 | } 41 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/report/ConditionEvaluationReportBuilder.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.report; 2 | 3 | import io.microsphere.annotation.Nonnull; 4 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 5 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 6 | import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; 7 | 8 | import java.util.LinkedHashMap; 9 | import java.util.Map; 10 | import java.util.concurrent.ConcurrentHashMap; 11 | 12 | import static java.util.Collections.unmodifiableMap; 13 | import static org.springframework.util.ObjectUtils.identityToString; 14 | 15 | /** 16 | * Spring Boot Condition evaluation report builder 17 | * 18 | * @author Mercy 19 | * @since 1.0.0 20 | */ 21 | abstract class ConditionEvaluationReportBuilder { 22 | 23 | private static final Map reports = new ConcurrentHashMap<>(); 24 | 25 | static ConditionEvaluationReport build(ConfigurableListableBeanFactory beanFactory) { 26 | return reports.computeIfAbsent(beanFactory, ConditionEvaluationReport::get); 27 | } 28 | 29 | static Map getReportsMap() { 30 | Map reportsMap = new LinkedHashMap<>(reports.size()); 31 | reports.forEach((beanFactory, report) -> { 32 | String id = getBeanFactoryId(beanFactory); 33 | reportsMap.put(id, report); 34 | }); 35 | return unmodifiableMap(reportsMap); 36 | } 37 | 38 | @Nonnull 39 | static String getBeanFactoryId(ConfigurableListableBeanFactory beanFactory) { 40 | if (beanFactory instanceof DefaultListableBeanFactory) { 41 | return ((DefaultListableBeanFactory) beanFactory).getSerializationId(); 42 | } 43 | return identityToString(beanFactory); 44 | } 45 | 46 | private ConditionEvaluationReportBuilder() { 47 | } 48 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionFailureAnalyzerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.diagnostics; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.boot.CommandLineRunner; 23 | import org.springframework.boot.SpringApplication; 24 | 25 | import static io.microsphere.collection.Sets.ofSet; 26 | import static io.microsphere.spring.boot.util.TestUtils.application; 27 | import static org.junit.jupiter.api.Assertions.assertThrows; 28 | 29 | /** 30 | * {@link ArtifactsCollisionFailureAnalyzer} Test 31 | * 32 | * @author Mercy 33 | * @see ArtifactsCollisionFailureAnalyzer 34 | * @since 1.0.0 35 | */ 36 | class ArtifactsCollisionFailureAnalyzerTest implements CommandLineRunner { 37 | 38 | @Test 39 | void test() { 40 | SpringApplication springApplication = application(getClass()); 41 | assertThrows(Exception.class, springApplication::run); 42 | } 43 | 44 | @Override 45 | public void run(String... args) throws Exception { 46 | throw new ArtifactsCollisionException("For testing", ofSet("test-groupId:test-artifactId")); 47 | } 48 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/report/ConditionEvaluationReportListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.report; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 24 | import org.springframework.boot.autoconfigure.condition.ConditionEvaluationReport; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | 27 | import java.util.Map; 28 | 29 | import static org.junit.jupiter.api.Assertions.assertFalse; 30 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; 31 | 32 | /** 33 | * {@link ConditionEvaluationReportListener} Test 34 | * 35 | * @author Mercy 36 | * @see ConditionEvaluationReportListener 37 | * @since 1.0.0 38 | */ 39 | @SpringBootTest( 40 | classes = ConditionEvaluationReportListenerTest.class, 41 | webEnvironment = NONE 42 | ) 43 | @EnableAutoConfiguration 44 | class ConditionEvaluationReportListenerTest { 45 | 46 | @Autowired 47 | private Map reportsMap; 48 | 49 | @Test 50 | void test() { 51 | assertFalse(reportsMap.isEmpty()); 52 | } 53 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/constants/SpringBootPropertyConstantsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.constants; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.boot.context.properties.source.ConfigurationPropertySources; 23 | 24 | import static io.microsphere.reflect.FieldUtils.getStaticFieldValue; 25 | import static io.microsphere.spring.boot.constants.SpringBootPropertyConstants.ATTACHED_PROPERTY_SOURCE_NAME; 26 | import static io.microsphere.spring.boot.constants.SpringBootPropertyConstants.SPRING_AUTO_CONFIGURE_EXCLUDE_PROPERTY_NAME; 27 | import static org.junit.jupiter.api.Assertions.assertEquals; 28 | 29 | /** 30 | * {@link SpringBootPropertyConstants} Test 31 | * 32 | * @author Mercy 33 | * @see SpringBootPropertyConstants 34 | * @since 1.0.0 35 | */ 36 | class SpringBootPropertyConstantsTest { 37 | 38 | @Test 39 | void testConstants() { 40 | assertEquals("spring.autoconfigure.exclude", SPRING_AUTO_CONFIGURE_EXCLUDE_PROPERTY_NAME); 41 | 42 | assertEquals("configurationProperties", ATTACHED_PROPERTY_SOURCE_NAME); 43 | assertEquals(getStaticFieldValue(ConfigurationPropertySources.class, "ATTACHED_PROPERTY_SOURCE_NAME"), ATTACHED_PROPERTY_SOURCE_NAME); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/properties/bind/util/BindHandlerUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context.properties.bind.util; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler; 23 | import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler; 24 | 25 | import static io.microsphere.spring.boot.context.properties.bind.util.BindHandlerUtils.createBindHandler; 26 | import static org.junit.jupiter.api.Assertions.assertInstanceOf; 27 | import static org.springframework.boot.context.properties.bind.BindHandler.DEFAULT; 28 | 29 | /** 30 | * {@link BindHandlerUtils} Test 31 | * 32 | * @author Mercy 33 | * @see BindHandlerUtils 34 | * @since 1.0.0 35 | */ 36 | class BindHandlerUtilsTest { 37 | 38 | @Test 39 | void testCreateBindHandler() { 40 | assertInstanceOf(NoUnboundElementsBindHandler.class, createBindHandler(false, false)); 41 | assertInstanceOf(DEFAULT.getClass(), createBindHandler(true, false)); 42 | assertInstanceOf(IgnoreErrorsBindHandler.class, createBindHandler(true, true)); 43 | assertInstanceOf(NoUnboundElementsBindHandler.class, createBindHandler(false, true)); 44 | } 45 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/report/ConditionsReportMessageBuilderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.report; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.beans.factory.ObjectProvider; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 25 | import org.springframework.boot.test.context.SpringBootTest; 26 | 27 | import static org.junit.jupiter.api.Assertions.assertNull; 28 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; 29 | 30 | /** 31 | * {@link ConditionsReportMessageBuilder} Test 32 | * 33 | * @author Mercy 34 | * @see ConditionsReportMessageBuilder 35 | * @since 1.0.0 36 | */ 37 | @SpringBootTest( 38 | classes = ConditionsReportMessageBuilderTest.class, 39 | webEnvironment = NONE, 40 | properties = { 41 | "microsphere.spring.boot.conditions.report.base-packages=org.springframework" 42 | } 43 | ) 44 | @EnableAutoConfiguration 45 | class ConditionsReportMessageBuilderTest { 46 | 47 | @Autowired 48 | private ObjectProvider builderProvider; 49 | 50 | @Test 51 | void testBuild() { 52 | assertNull(builderProvider.getIfAvailable()); 53 | } 54 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/SpringApplicationRunListenerAdapter.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.listener; 2 | 3 | import org.springframework.boot.ConfigurableBootstrapContext; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.SpringApplicationRunListener; 6 | import org.springframework.context.ConfigurableApplicationContext; 7 | import org.springframework.core.Ordered; 8 | import org.springframework.core.env.ConfigurableEnvironment; 9 | 10 | /** 11 | * {@link SpringApplicationRunListener} Adapter 12 | * 13 | * @author Mercy 14 | * @since 1.0.0 15 | */ 16 | public abstract class SpringApplicationRunListenerAdapter implements SpringApplicationRunListener, Ordered { 17 | 18 | protected final SpringApplication springApplication; 19 | 20 | protected final String[] args; 21 | 22 | private int order; 23 | 24 | public SpringApplicationRunListenerAdapter(SpringApplication springApplication, String[] args) { 25 | this.springApplication = springApplication; 26 | this.args = args; 27 | this.setOrder(0); 28 | } 29 | 30 | public void starting(ConfigurableBootstrapContext bootstrapContext) { 31 | } 32 | 33 | public void starting() { 34 | } 35 | 36 | public void environmentPrepared(ConfigurableEnvironment environment) { 37 | } 38 | 39 | public void contextPrepared(ConfigurableApplicationContext context) { 40 | } 41 | 42 | public void contextLoaded(ConfigurableApplicationContext context) { 43 | } 44 | 45 | public void started(ConfigurableApplicationContext context) { 46 | } 47 | 48 | public void running(ConfigurableApplicationContext context) { 49 | } 50 | 51 | public void failed(ConfigurableApplicationContext context, Throwable exception) { 52 | } 53 | 54 | public final SpringApplication getSpringApplication() { 55 | return springApplication; 56 | } 57 | 58 | public final String[] getArgs() { 59 | return args; 60 | } 61 | 62 | public final void setOrder(int order) { 63 | this.order = order; 64 | } 65 | 66 | @Override 67 | public final int getOrder() { 68 | return order; 69 | } 70 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/constants/PropertyConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.constants; 18 | 19 | import io.microsphere.annotation.ConfigurationProperty; 20 | 21 | import static io.microsphere.annotation.ConfigurationProperty.APPLICATION_SOURCE; 22 | import static io.microsphere.spring.constants.PropertyConstants.MICROSPHERE_SPRING_PROPERTY_NAME_PREFIX; 23 | 24 | /** 25 | * The Property constants for Microsphere Spring Boot 26 | * 27 | * @author Mercy 28 | * @since 1.0.0 29 | */ 30 | public interface PropertyConstants { 31 | 32 | /** 33 | * The property name prefix of Microsphere Spring Boot : "microsphere.spring.boot." 34 | */ 35 | String MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX = MICROSPHERE_SPRING_PROPERTY_NAME_PREFIX + "boot."; 36 | 37 | /** 38 | * The default value of Microsphere Spring Boot logging level : "TRACE" 39 | */ 40 | String DEFAULT_MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL = "TRACE"; 41 | 42 | /** 43 | * The property name of Microsphere Spring Boot logging level 44 | */ 45 | @ConfigurationProperty( 46 | defaultValue = DEFAULT_MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL, 47 | source = APPLICATION_SOURCE 48 | ) 49 | String MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME = MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX + "logging.level"; 50 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/env/PropertiesEmptyPropertySourceLoader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.env; 19 | 20 | import org.springframework.boot.env.PropertiesPropertySourceLoader; 21 | import org.springframework.boot.env.RandomValuePropertySource; 22 | import org.springframework.core.Ordered; 23 | import org.springframework.core.env.PropertySource; 24 | import org.springframework.core.io.Resource; 25 | 26 | import java.io.IOException; 27 | import java.util.List; 28 | 29 | import static io.microsphere.collection.Lists.ofList; 30 | 31 | /** 32 | * {@link PropertiesPropertySourceLoader} extension class to load the list of {@link PropertySource PropertySources} 33 | * with only one empty {@link PropertySource}. 34 | * 35 | * @author Mercy 36 | * @see PropertiesPropertySourceLoader 37 | * @since 1.0.0 38 | */ 39 | public class PropertiesEmptyPropertySourceLoader extends PropertiesPropertySourceLoader implements Ordered { 40 | 41 | @Override 42 | public List> load(String name, Resource resource) throws IOException { 43 | return ofList(emptyPropertySource(name)); 44 | } 45 | 46 | private PropertySource emptyPropertySource(String name) { 47 | return new RandomValuePropertySource(name); 48 | } 49 | 50 | @Override 51 | public int getOrder() { 52 | return 0; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/SpringApplicationDefaultPropertiesPostProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.env; 18 | 19 | import org.springframework.boot.SpringApplication; 20 | 21 | import java.util.Properties; 22 | import java.util.Set; 23 | 24 | import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; 25 | 26 | /** 27 | * {@link SpringApplication Spring Application} {@link DefaultPropertiesPostProcessor} to load the properties resources 28 | * being located in the {@link #DEFAULT_PROPERTIES_RESOURCES_PATTERN "classpath*:/META-INF/config/default/*.*"} 29 | * 30 | * @author Mercy 31 | * @see SpringApplication#setDefaultProperties(Properties) 32 | * @since 1.0.0 33 | */ 34 | public class SpringApplicationDefaultPropertiesPostProcessor implements DefaultPropertiesPostProcessor { 35 | 36 | /** 37 | * The resource pattern to load the properties resources. 38 | */ 39 | public static final String DEFAULT_PROPERTIES_RESOURCES_PATTERN = CLASSPATH_ALL_URL_PREFIX + "/META-INF/config/default/*.*"; 40 | 41 | @Override 42 | public void initializeResources(Set defaultPropertiesResources) { 43 | // Loads all PropertySource Class-Path resources with the wildcard pattern "/config/default/*.*" 44 | defaultPropertiesResources.add(DEFAULT_PROPERTIES_RESOURCES_PATTERN); 45 | } 46 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/ConfigurationPropertiesBeanPropertyChangedEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.bind; 18 | 19 | import io.microsphere.spring.context.event.BeanPropertyChangedEvent; 20 | import org.springframework.boot.context.properties.ConfigurationProperties; 21 | import org.springframework.boot.context.properties.source.ConfigurationProperty; 22 | 23 | /** 24 | * Event raised when the property of bean annotated {@link ConfigurationProperties @ConfigurationProperties} was changed. 25 | * 26 | * @param the type of the bean annotated with {@link ConfigurationProperties} 27 | * @author Mercy 28 | * @see ConfigurationProperties 29 | * @see BeanPropertyChangedEvent 30 | * @see EventPublishingConfigurationPropertiesBeanPropertyChangedListener 31 | * @since 1.0.0 32 | */ 33 | public class ConfigurationPropertiesBeanPropertyChangedEvent extends BeanPropertyChangedEvent { 34 | 35 | private final ConfigurationProperty configurationProperty; 36 | 37 | public ConfigurationPropertiesBeanPropertyChangedEvent(Object bean, String propertyName, Object oldValue, Object newValue, ConfigurationProperty configurationProperty) { 38 | super(bean, propertyName, oldValue, newValue); 39 | this.configurationProperty = configurationProperty; 40 | } 41 | 42 | public ConfigurationProperty getConfigurationProperty() { 43 | return configurationProperty; 44 | } 45 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/report/ConditionEvaluationSpringBootExceptionReporterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.report; 19 | 20 | 21 | import org.junit.jupiter.api.Test; 22 | import org.springframework.boot.SpringApplication; 23 | import org.springframework.context.ConfigurableApplicationContext; 24 | import org.springframework.context.support.GenericApplicationContext; 25 | 26 | import static io.microsphere.spring.boot.util.TestUtils.application; 27 | import static org.junit.jupiter.api.Assertions.assertThrows; 28 | 29 | /** 30 | * {@link ConditionEvaluationSpringBootExceptionReporter} Test 31 | * 32 | * @author Mercy 33 | * @see ConditionEvaluationSpringBootExceptionReporter 34 | * @since 1.0.0 35 | */ 36 | class ConditionEvaluationSpringBootExceptionReporterTest { 37 | 38 | @Test 39 | void testReportException() { 40 | ConfigurableApplicationContext context = new GenericApplicationContext(); 41 | ConditionEvaluationSpringBootExceptionReporter reporter = new ConditionEvaluationSpringBootExceptionReporter(context); 42 | reporter.reportException(new Throwable("For testing")); 43 | } 44 | 45 | @Test 46 | void testReportExceptionWithinSpringApplication() { 47 | SpringApplication springApplication = application(); 48 | springApplication.addInitializers(context -> { 49 | throw new RuntimeException("For testing"); 50 | }); 51 | assertThrows(RuntimeException.class, springApplication::run); 52 | } 53 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | io.github.microsphere-projects 7 | microsphere-build 8 | 0.2.2 9 | 10 | 4.0.0 11 | 12 | io.github.microsphere-projects 13 | microsphere-spring-boot 14 | ${revision} 15 | pom 16 | 17 | Microsphere :: Spring Boot 18 | Microsphere Spring Boot 19 | https://github.com/microsphere-projects/microsphere-spring-boot 20 | 21 | 22 | Microsphere 23 | https://github.com/microsphere-projects 24 | 25 | 26 | 27 | 28 | The Apache License, Version 2.0 29 | http://www.apache.org/licenses/LICENSE-2.0.txt 30 | 31 | 32 | 33 | 34 | 35 | mercyblitz 36 | Mercy Ma 37 | mercyblitz@gmail.com 38 | Microsphere 39 | 40 | lead 41 | architect 42 | developer 43 | 44 | 45 | 46 | 47 | 48 | git@github.com/microsphere-projects/microsphere-spring-boot.git 49 | scm:git:${project.scm.url} 50 | scm:git:ssh://${project.scm.url} 51 | 52 | 53 | 54 | 0.2.5-SNAPSHOT 55 | 17 56 | 57 | 58 | 59 | microsphere-spring-boot-parent 60 | microsphere-spring-boot-dependencies 61 | microsphere-spring-boot-core 62 | microsphere-spring-boot-actuator 63 | 64 | 65 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/LoggingOnceApplicationPreparedEventListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context; 19 | 20 | import org.springframework.boot.SpringApplication; 21 | import org.springframework.context.ConfigurableApplicationContext; 22 | 23 | import static io.microsphere.spring.boot.constants.PropertyConstants.DEFAULT_MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL; 24 | import static io.microsphere.spring.boot.util.SpringApplicationUtils.getLoggingLevel; 25 | import static io.microsphere.spring.boot.util.SpringApplicationUtils.log; 26 | 27 | /** 28 | * {@link OnceApplicationPreparedEventListener} class for logging with specified level. 29 | * 30 | * @author Mercy 31 | * @see OnceApplicationPreparedEventListener 32 | * @since 1.0.0 33 | */ 34 | public class LoggingOnceApplicationPreparedEventListener extends OnceApplicationPreparedEventListener { 35 | 36 | public LoggingOnceApplicationPreparedEventListener() { 37 | super.setOrder(LOWEST_PRECEDENCE); 38 | } 39 | 40 | @Override 41 | protected void onApplicationEvent(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context) { 42 | log(springApplication, args, context, "onApplicationPreparedEvent"); 43 | } 44 | 45 | @Override 46 | protected boolean isIgnored(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context) { 47 | String level = getLoggingLevel(context); 48 | return DEFAULT_MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL.equals(level); 49 | } 50 | } -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, and in the interest of 4 | fostering an open and welcoming community, we pledge to respect all people who 5 | contribute through reporting issues, posting feature requests, updating 6 | documentation, submitting pull requests or patches, and other activities. 7 | 8 | We are committed to making participation in this project a harassment-free 9 | experience for everyone, regardless of level of experience, gender, gender 10 | identity and expression, sexual orientation, disability, personal appearance, 11 | body size, race, ethnicity, age, religion, or nationality. 12 | 13 | Examples of unacceptable behavior by participants include: 14 | 15 | * The use of sexualized language or imagery 16 | * Personal attacks 17 | * Trolling or insulting/derogatory comments 18 | * Public or private harassment 19 | * Publishing other's private information, such as physical or electronic 20 | addresses, without explicit permission 21 | * Other unethical or unprofessional conduct 22 | 23 | Project maintainers have the right and responsibility to remove, edit, or 24 | reject comments, commits, code, wiki edits, issues, and other contributions 25 | that are not aligned to this Code of Conduct, or to ban temporarily or 26 | permanently any contributor for other behaviors that they deem inappropriate, 27 | threatening, offensive, or harmful. 28 | 29 | By adopting this Code of Conduct, project maintainers commit themselves to 30 | fairly and consistently applying these principles to every aspect of managing 31 | this project. Project maintainers who do not follow or enforce the Code of 32 | Conduct may be permanently removed from the project team. 33 | 34 | This Code of Conduct applies both within project spaces and in public spaces 35 | when an individual is representing the project or its community. 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 38 | reported by contacting a project maintainer at [mercyblitz@gmail.com](mailto:mercyblitz@gmail.com). All 39 | complaints will be reviewed and investigated and will result in a response that 40 | is deemed necessary and appropriate to the circumstances. Maintainers are 41 | obligated to maintain confidentiality with regard to the reporter of an 42 | incident. 43 | 44 | 45 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 46 | version 1.3.0, available at https://www.contributor-covenant.org/version/1/3/0/code-of-conduct.html 47 | 48 | [homepage]: https://www.contributor-covenant.org -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/ConditionalOnPropertyPrefix.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.condition; 18 | 19 | import org.springframework.context.annotation.Conditional; 20 | 21 | import java.lang.annotation.Retention; 22 | import java.lang.annotation.Target; 23 | 24 | import static java.lang.annotation.ElementType.METHOD; 25 | import static java.lang.annotation.ElementType.TYPE; 26 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 27 | 28 | /** 29 | * {@link Conditional} that checks if the prefix of properties are found in environment.. 30 | * 31 | *

Example Usage

32 | *

Single prefix

33 | *
{@code
34 |  * @ConditionalOnPropertyPrefix("myapp.config")
35 |  * public class MyConfig {
36 |  *     // This bean will only be loaded if any property with prefix "myapp.config." exists
37 |  * }
38 |  * }
39 | * 40 | *

Multiple prefixes

41 | *
{@code
42 |  * @ConditionalOnPropertyPrefix( {"feature.alpha", "feature.beta"} )
43 |  * public class FeatureConfig {
44 |  *     // Loaded if any property with prefix "feature.alpha." or "feature.beta." exists
45 |  * }
46 |  * }
47 | * 48 | * @author Mercy 49 | * @see OnPropertyPrefixCondition 50 | * @since 1.0.0 51 | */ 52 | @Retention(RUNTIME) 53 | @Target({TYPE, METHOD}) 54 | @Conditional(OnPropertyPrefixCondition.class) 55 | public @interface ConditionalOnPropertyPrefix { 56 | 57 | /** 58 | * The prefix values of properties. 59 | *

60 | * The prefix automatically ends 61 | * with a dot if not specified. 62 | * 63 | * @return prefix values of properties. 64 | */ 65 | String[] value(); 66 | 67 | } 68 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/env/DefaultPropertiesPostProcessor.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.env; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.core.Ordered; 5 | 6 | import java.util.Map; 7 | import java.util.Properties; 8 | import java.util.Set; 9 | 10 | /** 11 | * {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties"} Post Processor. 12 | * 13 | *

Example Usage

14 | *

Example usage in a custom {@link DefaultPropertiesPostProcessor}:

15 | * 16 | *
{@code
17 |  * public class CustomDefaultPropertiesPostProcessor implements DefaultPropertiesPostProcessor {
18 |  *
19 |  *     @Override
20 |  *     public void initializeResources(Set defaultPropertiesResources) {
21 |  *         defaultPropertiesResources.add("classpath*:META-INF/custom-default.properties");
22 |  *     }
23 |  *
24 |  *     @Override
25 |  *     public void postProcess(Map defaultProperties) {
26 |  *         // Add or modify default properties
27 |  *         defaultProperties.put("custom.property", "defaultValue");
28 |  *     }
29 |  * }
30 |  * }
31 | * 32 | *

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

33 | * 34 | *
{@code
35 |  * io.microsphere.spring.boot.env.DefaultPropertiesPostProcessor=\
36 |  * com.example.CustomDefaultPropertiesPostProcessor
37 |  * }
38 | * 39 | * @author Mercy 40 | * @see DefaultPropertiesApplicationListener 41 | * @since 1.0.0 42 | */ 43 | public interface DefaultPropertiesPostProcessor extends Ordered { 44 | 45 | /** 46 | * Initialize {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties}" resources 47 | * 48 | * @param defaultPropertiesResources {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties"} Resource path 49 | */ 50 | void initializeResources(Set defaultPropertiesResources); 51 | 52 | /** 53 | * Post handle {@link SpringApplication#setDefaultProperties (Properties) "defaultProperties"}, 54 | * after {@link #initializeResources(Set)} 55 | * 56 | * @param defaultProperties {@link SpringApplication#setDefaultProperties(Properties) "defaultProperties"} 57 | */ 58 | default void postProcess(Map defaultProperties) { 59 | } 60 | 61 | /** 62 | * Get the order of {@link DefaultPropertiesPostProcessor} 63 | * 64 | * @return {@link #LOWEST_PRECEDENCE} as default 65 | */ 66 | default int getOrder() { 67 | return LOWEST_PRECEDENCE; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/properties/util/ConfigurationPropertiesUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context.properties.util; 19 | 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.autoconfigure.web.ServerProperties; 24 | import org.springframework.boot.context.properties.ConfigurationProperties; 25 | import org.springframework.boot.context.properties.bind.Bindable; 26 | 27 | import static io.microsphere.spring.boot.context.properties.util.ConfigurationPropertiesUtils.CONFIGURATION_PROPERTIES_CLASS; 28 | import static io.microsphere.spring.boot.context.properties.util.ConfigurationPropertiesUtils.findConfigurationProperties; 29 | import static org.junit.jupiter.api.Assertions.assertSame; 30 | import static org.springframework.boot.context.properties.bind.Bindable.of; 31 | 32 | /** 33 | * {@link ConfigurationPropertiesUtils} Test 34 | * 35 | * @author Mercy 36 | * @see ConfigurationPropertiesUtils 37 | * @since 1.0.0 38 | */ 39 | class ConfigurationPropertiesUtilsTest { 40 | 41 | private Bindable bindable; 42 | 43 | @BeforeEach 44 | void setUp() { 45 | this.bindable = of(ServerProperties.class); 46 | } 47 | 48 | @Test 49 | void testFindConfigurationProperties() { 50 | ConfigurationProperties configurationProperties = ServerProperties.class.getAnnotation(CONFIGURATION_PROPERTIES_CLASS); 51 | this.bindable = this.bindable.withAnnotations(configurationProperties); 52 | assertSame(configurationProperties, findConfigurationProperties(this.bindable)); 53 | } 54 | 55 | @Test 56 | void testFindConfigurationPropertiesWithoutAnnotations() { 57 | ConfigurationProperties configurationProperties = ServerProperties.class.getAnnotation(CONFIGURATION_PROPERTIES_CLASS); 58 | assertSame(configurationProperties, findConfigurationProperties(this.bindable)); 59 | } 60 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/util/TestUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.util; 19 | 20 | import io.microsphere.annotation.Nullable; 21 | import org.springframework.boot.SpringApplication; 22 | import org.springframework.boot.autoconfigure.web.ServerProperties; 23 | import org.springframework.core.env.Environment; 24 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 25 | import org.springframework.core.io.support.ResourcePatternResolver; 26 | 27 | import static io.microsphere.util.ArrayUtils.combine; 28 | import static java.lang.String.valueOf; 29 | import static java.lang.Thread.currentThread; 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | import static org.springframework.boot.WebApplicationType.NONE; 32 | 33 | /** 34 | * The utilities class for testing 35 | * 36 | * @author Mercy 37 | * @see SpringApplication 38 | * @see ServerProperties 39 | * @since 1.0.0 40 | */ 41 | public abstract class TestUtils { 42 | 43 | public static SpringApplication application(Class... primarySources) { 44 | return application(currentThread().getContextClassLoader(), primarySources); 45 | } 46 | 47 | public static SpringApplication application(@Nullable ClassLoader classLoader, Class... primarySources) { 48 | SpringApplication springApplication = new SpringApplication(combine(Object.class, primarySources)); 49 | springApplication.setWebApplicationType(NONE); 50 | if (classLoader != null) { 51 | ResourcePatternResolver resourceLoader = new PathMatchingResourcePatternResolver(classLoader); 52 | springApplication.setResourceLoader(resourceLoader); 53 | } 54 | return springApplication; 55 | } 56 | 57 | public static void assertServerPropertiesPort(Environment environment, ServerProperties serverProperties) { 58 | assertEquals(environment.getProperty("server.port"), valueOf(serverProperties.getPort())); 59 | } 60 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListeners.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.bind; 18 | 19 | import org.springframework.boot.context.properties.bind.BindContext; 20 | import org.springframework.boot.context.properties.bind.Bindable; 21 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 22 | 23 | import java.util.function.Consumer; 24 | 25 | /** 26 | * Composite {@link BindListener} 27 | * 28 | * @author Mercy 29 | * @since 1.0.0 30 | */ 31 | class BindListeners implements BindListener { 32 | 33 | private final Iterable listeners; 34 | 35 | BindListeners(Iterable listeners) { 36 | this.listeners = listeners; 37 | } 38 | 39 | @Override 40 | public void onStart(ConfigurationPropertyName name, Bindable target, BindContext context) { 41 | iterate(listener -> listener.onStart(name, target, context)); 42 | } 43 | 44 | @Override 45 | public void onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 46 | iterate(listener -> listener.onSuccess(name, target, context, result)); 47 | } 48 | 49 | @Override 50 | public void onCreate(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 51 | iterate(listener -> listener.onCreate(name, target, context, result)); 52 | } 53 | 54 | @Override 55 | public void onFailure(ConfigurationPropertyName name, Bindable target, BindContext context, Exception error) { 56 | iterate(listener -> listener.onFailure(name, target, context, error)); 57 | } 58 | 59 | @Override 60 | public void onFinish(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 61 | iterate(listener -> listener.onFinish(name, target, context, result)); 62 | } 63 | 64 | private void iterate(Consumer listenerConsumer) { 65 | listeners.forEach(listenerConsumer); 66 | } 67 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | io.github.microsphere-projects 7 | microsphere-spring-boot-parent 8 | ${revision} 9 | ../microsphere-spring-boot-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | io.github.microsphere-projects 14 | microsphere-spring-boot-actuator 15 | ${revision} 16 | jar 17 | 18 | Microsphere :: Spring Boot :: Actuator 19 | Microsphere Spring Boot Actuator 20 | 21 | 22 | 23 | 24 | 25 | io.github.microsphere-projects 26 | microsphere-spring-boot-core 27 | ${revision} 28 | 29 | 30 | 31 | 32 | org.jolokia 33 | jolokia-core 34 | ${jolokia.version} 35 | 36 | 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-actuator 41 | true 42 | 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-starter-web 47 | true 48 | 49 | 50 | 51 | org.springframework.boot 52 | spring-boot-starter-webflux 53 | true 54 | 55 | 56 | 57 | org.springframework.boot 58 | spring-boot-configuration-processor 59 | true 60 | 61 | 62 | 63 | 64 | org.junit.jupiter 65 | junit-jupiter 66 | test 67 | 68 | 69 | 70 | org.springframework.boot 71 | spring-boot-starter-test 72 | test 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/properties/source/util/ConfigurationPropertyUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.source.util; 18 | 19 | import io.microsphere.spring.boot.context.properties.bind.BindListener; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.boot.autoconfigure.web.ServerProperties; 22 | import org.springframework.boot.context.properties.bind.BindContext; 23 | import org.springframework.boot.context.properties.bind.Bindable; 24 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 25 | 26 | import java.util.Map; 27 | 28 | import static io.microsphere.collection.Maps.ofMap; 29 | import static io.microsphere.spring.boot.context.properties.bind.util.BindUtils.bind; 30 | import static io.microsphere.spring.boot.context.properties.source.util.ConfigurationPropertyUtils.getPrefix; 31 | import static io.microsphere.spring.boot.context.properties.source.util.ConfigurationPropertyUtils.toDashedForm; 32 | import static org.junit.jupiter.api.Assertions.assertEquals; 33 | 34 | /** 35 | * {@link ConfigurationPropertyUtils} Test 36 | * 37 | * @author Mercy 38 | * @since 1.0.0 39 | */ 40 | class ConfigurationPropertyUtilsTest { 41 | 42 | @Test 43 | void testGetPrefix() { 44 | String prefix = "server"; 45 | Map properties = ofMap(prefix + ".port", "12345"); 46 | ServerProperties serverProperties = bind(properties, prefix, ServerProperties.class, new BindListener() { 47 | @Override 48 | public void onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 49 | assertEquals(prefix, getPrefix(name, context)); 50 | } 51 | }); 52 | assertEquals(12345, serverProperties.getPort()); 53 | } 54 | 55 | @Test 56 | void testGetPrefixForAlias() { 57 | } 58 | 59 | @Test 60 | void testToDashedForm() { 61 | assertEquals("my-name", toDashedForm("my-name")); 62 | assertEquals("my-name", toDashedForm("myName")); 63 | assertEquals("my-name", toDashedForm("MyName")); 64 | assertEquals("my-name", toDashedForm("my_name")); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/LoggingOnceApplicationPreparedEventListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context; 19 | 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 24 | 25 | import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME; 26 | 27 | /** 28 | * {@link LoggingOnceApplicationPreparedEventListener} Test 29 | * 30 | * @author Mercy 31 | * @see LoggingOnceApplicationPreparedEventListener 32 | * @since 1.0.0 33 | */ 34 | class LoggingOnceApplicationPreparedEventListenerTest extends AbstractApplicationPreparedEventTest { 35 | 36 | private LoggingOnceApplicationPreparedEventListener listener; 37 | 38 | @BeforeEach 39 | void setUp() { 40 | this.listener = new LoggingOnceApplicationPreparedEventListener(); 41 | } 42 | 43 | @Test 44 | void testOnApplicationEventOnIgnoredAndProcessed() { 45 | ApplicationPreparedEvent event = createEvent(); 46 | this.listener.onApplicationEvent(event); 47 | this.listener.onApplicationEvent(event); 48 | } 49 | 50 | @Test 51 | void testOnApplicationEventOnLoggingTrace() { 52 | testOnApplicationEventOnLogging("trace"); 53 | } 54 | 55 | @Test 56 | void testOnApplicationEventOnLoggingDebug() { 57 | testOnApplicationEventOnLogging("debug"); 58 | } 59 | 60 | @Test 61 | void testOnApplicationEventOnLoggingInfo() { 62 | testOnApplicationEventOnLogging("info"); 63 | } 64 | 65 | @Test 66 | void testOnApplicationEventOnLoggingWarn() { 67 | testOnApplicationEventOnLogging("warn"); 68 | } 69 | 70 | @Test 71 | void testOnApplicationEventOnLoggingError() { 72 | testOnApplicationEventOnLogging("error"); 73 | } 74 | 75 | void testOnApplicationEventOnLogging(String level) { 76 | String name = MICROSPHERE_SPRING_BOOT_LOGGING_LEVEL_PROPERTY_NAME; 77 | String arg = "--" + name + "=" + level; 78 | ApplicationPreparedEvent event = createEvent(arg); 79 | this.listener.onApplicationEvent(event); 80 | } 81 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/env/DefaultPropertiesPostProcessorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.env; 19 | 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | 24 | import java.util.Map; 25 | import java.util.Set; 26 | 27 | import static io.microsphere.collection.Maps.ofMap; 28 | import static io.microsphere.collection.Sets.ofSet; 29 | import static io.microsphere.util.ArrayUtils.ofArray; 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | import static org.springframework.core.Ordered.LOWEST_PRECEDENCE; 32 | 33 | /** 34 | * {@link DefaultPropertiesPostProcessor} Test 35 | * 36 | * @author Mercy 37 | * @see DefaultPropertiesPostProcessor 38 | * @since 1.0.0 39 | */ 40 | class DefaultPropertiesPostProcessorTest { 41 | 42 | private DefaultPropertiesPostProcessor processor; 43 | 44 | @BeforeEach 45 | void setUp() { 46 | this.processor = new DefaultPropertiesPostProcessor() { 47 | @Override 48 | public void initializeResources(Set defaultPropertiesResources) { 49 | } 50 | 51 | @Override 52 | public void postProcess(Map defaultProperties) { 53 | DefaultPropertiesPostProcessor.super.postProcess(defaultProperties); 54 | } 55 | 56 | @Override 57 | public int getOrder() { 58 | return DefaultPropertiesPostProcessor.super.getOrder(); 59 | } 60 | }; 61 | } 62 | 63 | @Test 64 | void testInitializeResources() { 65 | String[] resources = ofArray("a", "b", "c"); 66 | Set defaultPropertiesResources = ofSet(resources); 67 | this.processor.initializeResources(defaultPropertiesResources); 68 | assertEquals(ofSet(resources), defaultPropertiesResources); 69 | } 70 | 71 | @Test 72 | void testPostProcess() { 73 | Map defaultProperties = ofMap("a", "1", "b", "2", "c", "3"); 74 | this.processor.postProcess(defaultProperties); 75 | assertEquals(ofMap("a", "1", "b", "2", "c", "3"), defaultProperties); 76 | } 77 | 78 | @Test 79 | void testGetOrder() { 80 | assertEquals(LOWEST_PRECEDENCE, this.processor.getOrder()); 81 | } 82 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.metadata; 18 | 19 | import org.junit.jupiter.api.BeforeEach; 20 | import org.junit.jupiter.api.Test; 21 | import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata; 22 | import org.springframework.core.io.DefaultResourceLoader; 23 | import org.springframework.core.io.Resource; 24 | import org.springframework.core.io.support.ResourcePatternResolver; 25 | 26 | import java.io.IOException; 27 | 28 | import static org.junit.jupiter.api.Assertions.assertNotNull; 29 | import static org.junit.jupiter.api.Assertions.assertTrue; 30 | 31 | /** 32 | * {@link ConfigurationMetadataReader} Test 33 | * 34 | * @author Mercy 35 | * @since 1.0.0 36 | */ 37 | class ConfigurationMetadataReaderTest { 38 | 39 | private ConfigurationMetadataReader reader; 40 | 41 | @BeforeEach 42 | void setUp() { 43 | this.reader = new ConfigurationMetadataReader(); 44 | } 45 | 46 | @Test 47 | void test() { 48 | ConfigurationMetadata metadata = this.reader.read(); 49 | assertTrue(metadata.getItems().size() > 1); 50 | } 51 | 52 | @Test 53 | void testOnLoadingResourceFailed() { 54 | this.reader.setResourceLoader(new ResourcePatternResolver() { 55 | 56 | @Override 57 | public Resource getResource(String location) { 58 | throw new RuntimeException("For testing"); 59 | } 60 | 61 | @Override 62 | public ClassLoader getClassLoader() { 63 | throw new RuntimeException("For testing"); 64 | } 65 | 66 | @Override 67 | public Resource[] getResources(String locationPattern) throws IOException { 68 | throw new IOException("For testing"); 69 | } 70 | }); 71 | ConfigurationMetadata metadata = this.reader.read(); 72 | assertTrue(metadata.getItems().isEmpty()); 73 | 74 | } 75 | 76 | @Test 77 | void testGetResourcePatternResolver() { 78 | assertNotNull(this.reader.getResourcePatternResolver()); 79 | 80 | this.reader.setResourceLoader(new DefaultResourceLoader()); 81 | assertNotNull(this.reader.getResourcePatternResolver()); 82 | } 83 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/ConfigurationMetadataEndpoint.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.actuate.endpoint; 18 | 19 | import io.microsphere.spring.boot.env.config.metadata.ConfigurationMetadataRepository; 20 | import org.springframework.boot.actuate.endpoint.OperationResponseBody; 21 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint; 22 | import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; 23 | import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata; 24 | import org.springframework.boot.configurationprocessor.metadata.ItemMetadata; 25 | 26 | import java.util.Collection; 27 | 28 | /** 29 | * {@link Endpoint @Endpoint} to expose the {@link ConfigurationMetadata Configuration Metadata} that was generated by 30 | * "org.springframework.boot:spring-boot-configuration-processor" 31 | * 32 | * @author Mercy 33 | * @see ConfigurationMetadata 34 | * @see ConfigurationMetadataRepository 35 | * @since 1.0.0 36 | */ 37 | @Endpoint(id = "configMetadata") 38 | public class ConfigurationMetadataEndpoint { 39 | 40 | private final ConfigurationMetadataRepository configurationMetadataRepository; 41 | 42 | public ConfigurationMetadataEndpoint(ConfigurationMetadataRepository configurationMetadataRepository) { 43 | this.configurationMetadataRepository = configurationMetadataRepository; 44 | } 45 | 46 | @ReadOperation 47 | public ConfigurationMetadataDescriptor getConfigurationMetadata() { 48 | ConfigurationMetadataDescriptor configurationMetadata = new ConfigurationMetadataDescriptor(); 49 | configurationMetadata.groups = this.configurationMetadataRepository.getGroups(); 50 | configurationMetadata.properties = this.configurationMetadataRepository.getProperties(); 51 | return configurationMetadata; 52 | } 53 | 54 | /** 55 | * The Descriptor class for {@link ConfigurationMetadata} 56 | */ 57 | public static class ConfigurationMetadataDescriptor implements OperationResponseBody { 58 | 59 | private Collection groups; 60 | 61 | private Collection properties; 62 | 63 | public Collection getGroups() { 64 | return groups; 65 | } 66 | 67 | public Collection getProperties() { 68 | return properties; 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorAutoConfigurationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.actuate.autoconfigure; 18 | 19 | import org.junit.jupiter.api.Test; 20 | import org.springframework.beans.factory.annotation.Autowired; 21 | import org.springframework.beans.factory.annotation.Value; 22 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 23 | import org.springframework.boot.test.context.SpringBootTest; 24 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 25 | 26 | import static org.junit.jupiter.api.Assertions.assertEquals; 27 | import static org.junit.jupiter.api.Assertions.assertNotNull; 28 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.NONE; 29 | 30 | /** 31 | * {@link ActuatorAutoConfiguration} Test 32 | * 33 | * @author Mercy 34 | * @see ActuatorAutoConfiguration 35 | * @since 1.0.0 36 | */ 37 | @SpringBootTest( 38 | webEnvironment = NONE, 39 | classes = { 40 | ActuatorAutoConfigurationTest.class 41 | }, properties = { 42 | "microsphere.spring.boot.actuator.task-scheduler.pool-size=2", 43 | "microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix=my-prefix", 44 | 45 | }) 46 | @EnableAutoConfiguration 47 | class ActuatorAutoConfigurationTest { 48 | 49 | @Autowired 50 | @SuppressWarnings("unchecked") 51 | private ThreadPoolTaskScheduler actuatorTaskScheduler; 52 | 53 | @Value("${microsphere.spring.boot.actuator.task-scheduler.pool-size}") 54 | private int poolSize; 55 | 56 | @Value("${microsphere.spring.boot.actuator.task-scheduler.thread-name-prefix}") 57 | private String prefix; 58 | 59 | @Test 60 | void testActuatorTaskScheduler() { 61 | assertNotNull(actuatorTaskScheduler, "Actuator task scheduler should not be null"); 62 | assertEquals(prefix, actuatorTaskScheduler.getThreadNamePrefix(), "Thread name prefix should match"); 63 | assertEquals(0, actuatorTaskScheduler.getPoolSize(), "Pool size should match"); 64 | actuatorTaskScheduler.execute(() -> { 65 | }); 66 | assertEquals(1, actuatorTaskScheduler.getPoolSize(), "Pool size should match"); 67 | for (int i = 0; i < 9; i++) { 68 | actuatorTaskScheduler.execute(() -> { 69 | }); 70 | } 71 | assertEquals(poolSize, actuatorTaskScheduler.getPoolSize(), "Pool size should match"); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/condition/OnPropertyPrefixCondition.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.condition; 18 | 19 | import io.microsphere.spring.core.annotation.ResolvablePlaceholderAnnotationAttributes; 20 | import org.springframework.boot.autoconfigure.condition.ConditionOutcome; 21 | import org.springframework.boot.autoconfigure.condition.SpringBootCondition; 22 | import org.springframework.context.annotation.Condition; 23 | import org.springframework.context.annotation.ConditionContext; 24 | import org.springframework.core.annotation.AnnotationAttributes; 25 | import org.springframework.core.env.ConfigurableEnvironment; 26 | import org.springframework.core.type.AnnotatedTypeMetadata; 27 | 28 | import static io.microsphere.spring.core.annotation.ResolvablePlaceholderAnnotationAttributes.of; 29 | import static io.microsphere.spring.core.env.PropertySourcesUtils.findPropertyNames; 30 | import static io.microsphere.util.ArrayUtils.arrayToString; 31 | import static org.springframework.boot.autoconfigure.condition.ConditionOutcome.match; 32 | import static org.springframework.boot.autoconfigure.condition.ConditionOutcome.noMatch; 33 | import static org.springframework.core.annotation.AnnotationAttributes.fromMap; 34 | 35 | /** 36 | * {@link Condition} that checks if the prefix of properties are found in environment. 37 | * 38 | * @author Mercy 39 | * @see SpringBootCondition 40 | * @see ConditionalOnPropertyPrefix 41 | * @since 1.0.0 42 | */ 43 | class OnPropertyPrefixCondition extends SpringBootCondition { 44 | 45 | @Override 46 | public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { 47 | 48 | AnnotationAttributes annotationAttributes = fromMap(metadata.getAnnotationAttributes(ConditionalOnPropertyPrefix.class.getName())); 49 | 50 | ConfigurableEnvironment environment = (ConfigurableEnvironment) context.getEnvironment(); 51 | 52 | ResolvablePlaceholderAnnotationAttributes attributes = of(annotationAttributes, environment); 53 | 54 | String[] prefixValues = attributes.getStringArray("value"); 55 | 56 | boolean noMatched = findPropertyNames(environment, propertyName -> { 57 | for (String prefix : prefixValues) { 58 | if (propertyName.startsWith(prefix)) { 59 | return true; 60 | } 61 | } 62 | return false; 63 | }).isEmpty(); 64 | 65 | return noMatched ? noMatch("The prefix values " + arrayToString(prefixValues) + " were not found in Environment!") : match(); 66 | } 67 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/util/BindHandlerUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context.properties.bind.util; 19 | 20 | import io.microsphere.annotation.Nonnull; 21 | import io.microsphere.util.Utils; 22 | import org.springframework.boot.context.properties.bind.BindHandler; 23 | import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler; 24 | import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler; 25 | import org.springframework.boot.context.properties.source.UnboundElementsSourceFilter; 26 | 27 | import static org.springframework.boot.context.properties.bind.BindHandler.DEFAULT; 28 | 29 | /** 30 | * The utilities class of {@link BindHandler} 31 | * 32 | * @author Mercy 33 | * @see BindHandler 34 | * @see IgnoreErrorsBindHandler 35 | * @see NoUnboundElementsBindHandler 36 | * @since 1.0.0 37 | */ 38 | public abstract class BindHandlerUtils implements Utils { 39 | 40 | /** 41 | * Create a {@link BindHandler} instance based on the given flags. 42 | *

Example Usage

43 | *
{@code
44 |      * // Create a handler that ignores both unknown and invalid fields
45 |      * BindHandler handler = BindHandlerUtils.createBindHandler(true, true);
46 |      *
47 |      * // Create a handler that does not ignore any fields
48 |      * BindHandler handler = BindHandlerUtils.createBindHandler(false, false);
49 |      *
50 |      * // Create a handler that ignores only invalid fields
51 |      * BindHandler handler = BindHandlerUtils.createBindHandler(true, false);
52 |      *
53 |      * // Create a handler that ignores only unknown fields
54 |      * BindHandler handler = BindHandlerUtils.createBindHandler(false, true);
55 |      * }
56 | * 57 | * @param ignoreUnknownFields whether to ignore unknown fields 58 | * @param ignoreInvalidFields whether to ignore invalid fields 59 | * @return a {@link BindHandler} instance 60 | */ 61 | @Nonnull 62 | public static BindHandler createBindHandler(boolean ignoreUnknownFields, boolean ignoreInvalidFields) { 63 | BindHandler handler = DEFAULT; 64 | if (ignoreInvalidFields) { 65 | handler = new IgnoreErrorsBindHandler(handler); 66 | } 67 | if (!ignoreUnknownFields) { 68 | UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter(); 69 | handler = new NoUnboundElementsBindHandler(handler, filter); 70 | } 71 | return handler; 72 | } 73 | 74 | 75 | private BindHandlerUtils() { 76 | } 77 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.config; 18 | 19 | import io.microsphere.spring.boot.domain.User; 20 | import io.microsphere.spring.context.config.ConfigurationBeanBinder; 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.junit.jupiter.api.extension.ExtendWith; 24 | import org.springframework.beans.factory.annotation.Autowired; 25 | import org.springframework.boot.context.properties.bind.BindException; 26 | import org.springframework.core.env.ConfigurableEnvironment; 27 | import org.springframework.test.context.ContextConfiguration; 28 | import org.springframework.test.context.TestPropertySource; 29 | import org.springframework.test.context.junit.jupiter.SpringExtension; 30 | 31 | import java.util.Map; 32 | 33 | import static io.microsphere.spring.core.env.PropertySourcesUtils.getSubProperties; 34 | import static java.lang.Integer.valueOf; 35 | import static org.junit.jupiter.api.Assertions.assertEquals; 36 | import static org.junit.jupiter.api.Assertions.assertThrows; 37 | 38 | /** 39 | * {@link BindableConfigurationBeanBinder} Test 40 | * 41 | * @author Mercy 42 | * @since 1.0.0 43 | */ 44 | @ExtendWith(SpringExtension.class) 45 | @TestPropertySource(properties = { 46 | "user.name=mercyblitz", 47 | "user.age=37" 48 | }) 49 | @ContextConfiguration( 50 | classes = BindableConfigurationBeanBinder.class 51 | ) 52 | class BindableConfigurationBeanBinderTest { 53 | 54 | @Autowired 55 | private ConfigurationBeanBinder beanBinder; 56 | 57 | @Autowired 58 | private ConfigurableEnvironment environment; 59 | 60 | @BeforeEach 61 | void setUp() { 62 | this.beanBinder.setConversionService(this.environment.getConversionService()); 63 | } 64 | 65 | @Test 66 | void testBind() { 67 | User user = new User(); 68 | Map properties = getSubProperties(environment.getPropertySources(), "user"); 69 | 70 | beanBinder.bind(properties, true, true, user); 71 | assertUser(user); 72 | 73 | beanBinder.bind(properties, true, false, user); 74 | assertUser(user); 75 | 76 | assertThrows(BindException.class, () -> beanBinder.bind(properties, false, true, user)); 77 | 78 | assertThrows(BindException.class, () -> beanBinder.bind(properties, false, false, user)); 79 | } 80 | 81 | void assertUser(User user) { 82 | assertEquals("mercyblitz", user.getName()); 83 | assertEquals(valueOf(37), user.getAge()); 84 | } 85 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/env/config/metadata/ConfigurationMetadataRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.env.config.metadata; 19 | 20 | 21 | import io.microsphere.spring.boot.context.properties.metadata.ConfigurationMetadataReader; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.beans.factory.annotation.Autowired; 24 | import org.springframework.boot.configurationprocessor.metadata.ItemHint; 25 | import org.springframework.boot.configurationprocessor.metadata.ItemMetadata; 26 | import org.springframework.boot.test.context.SpringBootTest; 27 | 28 | import java.util.Collection; 29 | import java.util.List; 30 | import java.util.Set; 31 | 32 | import static org.junit.jupiter.api.Assertions.assertFalse; 33 | import static org.junit.jupiter.api.Assertions.assertNotNull; 34 | import static org.junit.jupiter.api.Assertions.assertTrue; 35 | 36 | 37 | /** 38 | * {@link ConfigurationMetadataRepository} Test 39 | * 40 | * @author Mercy 41 | * @see ConfigurationMetadataRepository 42 | * @since 1.0.0 43 | */ 44 | @SpringBootTest(classes = { 45 | ConfigurationMetadataReader.class, 46 | ConfigurationMetadataRepository.class, 47 | ConfigurationMetadataRepositoryTest.class, 48 | }) 49 | class ConfigurationMetadataRepositoryTest { 50 | 51 | @Autowired 52 | private ConfigurationMetadataRepository repository; 53 | 54 | @Test 55 | void test() { 56 | Collection groups = repository.getGroups(); 57 | assertFalse(groups.isEmpty()); 58 | 59 | Set propertyGroups = repository.getPropertyGroups(); 60 | assertFalse(propertyGroups.isEmpty()); 61 | 62 | for (String propertyGroup : propertyGroups) { 63 | ItemMetadata group = repository.getGroup(propertyGroup); 64 | assertTrue(groups.contains(group)); 65 | } 66 | 67 | Collection items = repository.getProperties(); 68 | assertFalse(items.isEmpty()); 69 | 70 | Set propertyNames = repository.getPropertyNames(); 71 | assertFalse(propertyNames.isEmpty()); 72 | 73 | for (String propertyName : propertyNames) { 74 | ItemMetadata item = repository.getProperty(propertyName); 75 | List hints = repository.getHints(propertyName); 76 | assertTrue(items.contains(item)); 77 | assertNotNull(hints); 78 | } 79 | 80 | ConfigurationMetadataReader configurationMetadataReader = repository.getConfigurationMetadataReader(); 81 | assertNotNull(configurationMetadataReader); 82 | 83 | } 84 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/autoconfigure/ApplicationAutoConfigurationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.autoconfigure; 18 | 19 | import io.microsphere.spring.context.event.BeanListener; 20 | import io.microsphere.spring.context.event.BeanTimeStatistics; 21 | import io.microsphere.spring.context.event.LoggingBeanListener; 22 | import jakarta.annotation.Resource; 23 | import org.junit.jupiter.api.Test; 24 | import org.springframework.beans.factory.ObjectProvider; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 27 | import org.springframework.boot.test.context.SpringBootTest; 28 | 29 | import java.util.List; 30 | 31 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; 32 | 33 | /** 34 | * Application AutoConfiguration Test 35 | * 36 | * @author Mercy 37 | * @since 1.0.0 38 | */ 39 | @SpringBootTest(classes = { 40 | ApplicationAutoConfigurationTest.class, 41 | ApplicationAutoConfigurationTest.TestConfig.class 42 | }, 43 | properties = { 44 | "server.port=12345", 45 | "spring.mvc.dispatchTraceRequest=true", 46 | "spring.mvc.format.date=dd/MM/yyyy", 47 | "logging.level.io.microsphere.spring=DEBUG" 48 | }, 49 | webEnvironment = RANDOM_PORT) 50 | @EnableAutoConfiguration 51 | class ApplicationAutoConfigurationTest { 52 | 53 | @Test 54 | void test() { 55 | } 56 | 57 | static class TestConfig { 58 | 59 | private final ObjectProvider beanListeners; 60 | 61 | private final ObjectProvider> beanListenersList; 62 | 63 | @Autowired 64 | private ObjectProvider beanTimeStatisticsObjectProvider; 65 | 66 | @Autowired 67 | private ObjectProvider loggingBeanListenerObjectProvider; 68 | 69 | @Resource 70 | private BeanTimeStatistics beanTimeStatistics; 71 | 72 | @Resource(type = LoggingBeanListener.class) 73 | private LoggingBeanListener loggingBeanListener; 74 | 75 | @Resource 76 | public void setLoggingBeanListener(LoggingBeanListener loggingBeanListener) { 77 | 78 | } 79 | 80 | public TestConfig(ObjectProvider beanListeners, 81 | ObjectProvider> beanListenersList) { 82 | this.beanListeners = beanListeners; 83 | this.beanListenersList = beanListenersList; 84 | } 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/diagnostics/ArtifactsCollisionResourceResolver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.diagnostics; 19 | 20 | import io.microsphere.classloading.Artifact; 21 | import io.microsphere.classloading.ArtifactResourceResolver; 22 | import io.microsphere.classloading.MavenArtifactResourceResolver; 23 | 24 | import java.io.File; 25 | import java.net.URL; 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | import static io.microsphere.lang.function.ThrowableSupplier.execute; 30 | import static io.microsphere.net.URLUtils.resolveArchiveFile; 31 | import static io.microsphere.util.ClassLoaderUtils.getClassResource; 32 | import static io.microsphere.util.ServiceLoaderUtils.loadServices; 33 | 34 | /** 35 | * {@link ArtifactResourceResolver} for artifacts collision 36 | * 37 | * @author Mercy 38 | * @see ArtifactResourceResolver 39 | * @since 1.0.0 40 | */ 41 | public class ArtifactsCollisionResourceResolver implements ArtifactResourceResolver { 42 | 43 | private static boolean enabled = false; 44 | 45 | private ArtifactResourceResolver delegate = new MavenArtifactResourceResolver(); 46 | 47 | private static List resolvers; 48 | 49 | static { 50 | resolvers = new ArrayList<>(); 51 | for (ArtifactResourceResolver resolver : loadServices(ArtifactResourceResolver.class)) { 52 | if (resolver instanceof ArtifactsCollisionResourceResolver) { 53 | continue; 54 | } 55 | resolvers.add(resolver); 56 | } 57 | } 58 | 59 | @Override 60 | public Artifact resolve(URL resourceURL) { 61 | if (enabled) { 62 | Artifact artifact = doResolve(resourceURL); 63 | if (artifact == null) { 64 | URL classResource = getClassResource(ArtifactResourceResolver.class); 65 | File artifactFile = resolveArchiveFile(classResource); 66 | URL artifactResource = execute(artifactFile::toURL); 67 | return delegate.resolve(artifactResource); 68 | } 69 | } 70 | return null; 71 | } 72 | 73 | Artifact doResolve(URL resourceURL) { 74 | for (ArtifactResourceResolver resolver : resolvers) { 75 | Artifact artifact = resolver.resolve(resourceURL); 76 | if (artifact != null) { 77 | return artifact; 78 | } 79 | } 80 | return null; 81 | } 82 | 83 | static void enable() { 84 | enabled = true; 85 | } 86 | 87 | static void disable() { 88 | enabled = false; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/properties/bind/BindListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context.properties.bind; 19 | 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.context.properties.bind.BindContext; 24 | import org.springframework.boot.context.properties.bind.Bindable; 25 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 26 | 27 | /** 28 | * {@link BindListener} Test 29 | * 30 | * @author Mercy 31 | * @see BindListener 32 | * @since 1.0.0 33 | */ 34 | class BindListenerTest { 35 | 36 | private BindListener listener; 37 | 38 | @BeforeEach 39 | void setUp() { 40 | listener = new BindListener() { 41 | @Override 42 | public void onStart(ConfigurationPropertyName name, Bindable target, BindContext context) { 43 | BindListener.super.onStart(name, target, context); 44 | } 45 | 46 | @Override 47 | public void onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 48 | BindListener.super.onSuccess(name, target, context, result); 49 | } 50 | 51 | @Override 52 | public void onCreate(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 53 | BindListener.super.onCreate(name, target, context, result); 54 | } 55 | 56 | @Override 57 | public void onFailure(ConfigurationPropertyName name, Bindable target, BindContext context, Exception error) { 58 | BindListener.super.onFailure(name, target, context, error); 59 | } 60 | 61 | @Override 62 | public void onFinish(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 63 | BindListener.super.onFinish(name, target, context, result); 64 | } 65 | }; 66 | } 67 | 68 | @Test 69 | void testOnStart() { 70 | this.listener.onStart(null, null, null); 71 | } 72 | 73 | @Test 74 | void testOnSuccess() { 75 | this.listener.onSuccess(null, null, null, null); 76 | } 77 | 78 | @Test 79 | void testOnCreate() { 80 | this.listener.onCreate(null, null, null, null); 81 | } 82 | 83 | @Test 84 | void testOnFailure() { 85 | this.listener.onFailure(null, null, null, null); 86 | } 87 | 88 | @Test 89 | void testOnFinish() { 90 | this.listener.onFinish(null, null, null, null); 91 | } 92 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/listener/LoggingSpringApplicationRunListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.listener; 19 | 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.ConfigurableBootstrapContext; 24 | import org.springframework.boot.DefaultBootstrapContext; 25 | import org.springframework.context.ConfigurableApplicationContext; 26 | import org.springframework.context.support.GenericApplicationContext; 27 | 28 | import static io.microsphere.spring.boot.util.TestUtils.application; 29 | import static io.microsphere.util.StringUtils.EMPTY_STRING_ARRAY; 30 | import static org.junit.jupiter.api.Assertions.assertEquals; 31 | 32 | /** 33 | * {@link LoggingSpringApplicationRunListener} Test 34 | * 35 | * @author Mercy 36 | * @see LoggingSpringApplicationRunListener 37 | * @since 1.0.0 38 | */ 39 | class LoggingSpringApplicationRunListenerTest { 40 | 41 | private LoggingSpringApplicationRunListener listener; 42 | 43 | private ConfigurableBootstrapContext bootstrapContext; 44 | 45 | private ConfigurableApplicationContext context; 46 | 47 | @BeforeEach 48 | void setUp() { 49 | this.listener = new LoggingSpringApplicationRunListener(application(getClass()), EMPTY_STRING_ARRAY); 50 | this.bootstrapContext = new DefaultBootstrapContext(); 51 | this.context = new GenericApplicationContext(); 52 | } 53 | 54 | @Test 55 | void testStartingWithBootstrapContext() { 56 | this.listener.starting(this.bootstrapContext); 57 | } 58 | 59 | @Test 60 | void testStarting() { 61 | this.listener.starting(); 62 | } 63 | 64 | @Test 65 | void testEnvironmentPrepared() { 66 | this.listener.environmentPrepared(this.context.getEnvironment()); 67 | } 68 | 69 | @Test 70 | void testContextPrepared() { 71 | this.listener.contextPrepared(this.context); 72 | } 73 | 74 | @Test 75 | void testContextLoaded() { 76 | this.listener.contextLoaded(this.context); 77 | } 78 | 79 | @Test 80 | void testStarted() { 81 | this.listener.started(this.context); 82 | } 83 | 84 | @Test 85 | void testRunning() { 86 | this.listener.running(this.context); 87 | } 88 | 89 | @Test 90 | void testFailed() { 91 | this.listener.failed(context, new Throwable("For testing")); 92 | } 93 | 94 | @Test 95 | void testGetOrder() { 96 | assertEquals(0, this.listener.getOrder()); 97 | this.listener.setOrder(1); 98 | assertEquals(1, this.listener.getOrder()); 99 | } 100 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/env/DefaultPropertiesApplicationListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.env; 19 | 20 | 21 | import io.microsphere.spring.boot.util.TestUtils; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.SpringApplication; 24 | import org.springframework.context.ConfigurableApplicationContext; 25 | import org.springframework.core.env.ConfigurableEnvironment; 26 | import org.springframework.core.io.Resource; 27 | import org.springframework.core.io.support.ResourcePatternResolver; 28 | 29 | import java.io.IOException; 30 | import java.net.URLClassLoader; 31 | 32 | import static io.microsphere.util.ArrayUtils.ofArray; 33 | import static java.lang.Thread.currentThread; 34 | import static org.junit.jupiter.api.Assertions.assertEquals; 35 | import static org.junit.jupiter.api.Assertions.assertNull; 36 | 37 | /** 38 | * {@link DefaultPropertiesApplicationListener} Test 39 | * 40 | * @author Mercy 41 | * @see DefaultPropertiesApplicationListener 42 | * @since 1.0.0 43 | */ 44 | class DefaultPropertiesApplicationListenerTest { 45 | 46 | @Test 47 | void testOnApplicationEvent() { 48 | SpringApplication springApplication = application(); 49 | ConfigurableApplicationContext context = springApplication.run(); 50 | ConfigurableEnvironment environment = context.getEnvironment(); 51 | assertEquals("test", environment.getProperty("test.name")); 52 | } 53 | 54 | @Test 55 | void testOnApplicationEventOnIOException() { 56 | SpringApplication springApplication = application(); 57 | ResourcePatternResolver delegate = (ResourcePatternResolver) springApplication.getResourceLoader(); 58 | 59 | ResourcePatternResolver resourceLoader = new ResourcePatternResolver() { 60 | 61 | @Override 62 | public Resource getResource(String location) { 63 | return delegate.getResource(location); 64 | } 65 | 66 | @Override 67 | public ClassLoader getClassLoader() { 68 | return delegate.getClassLoader(); 69 | } 70 | 71 | @Override 72 | public Resource[] getResources(String locationPattern) throws IOException { 73 | throw new IOException("For testing"); 74 | } 75 | }; 76 | 77 | springApplication.setResourceLoader(resourceLoader); 78 | ConfigurableApplicationContext context = springApplication.run(); 79 | ConfigurableEnvironment environment = context.getEnvironment(); 80 | assertNull(environment.getProperty("test.name")); 81 | } 82 | 83 | private SpringApplication application() { 84 | ClassLoader classLoader = new URLClassLoader(ofArray(), currentThread().getContextClassLoader()); 85 | return TestUtils.application(classLoader); 86 | } 87 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/autoconfigure/ActuatorEndpointsAutoConfigurationTest.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.actuate.autoconfigure; 2 | 3 | import io.microsphere.spring.boot.actuate.endpoint.ArtifactsEndpoint; 4 | import io.microsphere.spring.boot.actuate.endpoint.ConfigurationMetadataEndpoint; 5 | import io.microsphere.spring.boot.actuate.endpoint.ConfigurationPropertiesEndpoint; 6 | import io.microsphere.spring.boot.actuate.endpoint.ConfigurationPropertiesEndpoint.ConfigurationPropertiesDescriptor; 7 | import io.microsphere.spring.boot.actuate.endpoint.WebEndpoints; 8 | import org.junit.jupiter.api.Test; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 11 | import org.springframework.boot.builder.SpringApplicationBuilder; 12 | import org.springframework.boot.test.context.SpringBootTest; 13 | import org.springframework.context.annotation.PropertySource; 14 | import org.springframework.test.context.TestPropertySource; 15 | 16 | import java.util.Map; 17 | 18 | import static org.junit.jupiter.api.Assertions.assertFalse; 19 | import static org.junit.jupiter.api.Assertions.assertNotNull; 20 | import static org.springframework.boot.WebApplicationType.SERVLET; 21 | import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; 22 | 23 | /** 24 | * {@link ActuatorEndpointsAutoConfiguration} Test 25 | * 26 | * @author Mercy 27 | * @see ActuatorEndpointsAutoConfiguration 28 | * @since 1.0.0 29 | */ 30 | @SpringBootTest( 31 | webEnvironment = RANDOM_PORT, 32 | classes = { 33 | ActuatorEndpointsAutoConfigurationTest.class, 34 | }, 35 | properties = { 36 | "management.endpoint.loggers.enabled=false" 37 | } 38 | ) 39 | @PropertySource(value = "classpath:META-INF/config/default/endpoints.properties") 40 | @TestPropertySource(value = "classpath:META-INF/config/default/endpoints.properties") 41 | @EnableAutoConfiguration 42 | class ActuatorEndpointsAutoConfigurationTest { 43 | 44 | @Autowired 45 | private ArtifactsEndpoint artifactsEndpoint; 46 | 47 | @Autowired 48 | private WebEndpoints webEndpoints; 49 | 50 | @Autowired 51 | private ConfigurationMetadataEndpoint configurationMetadataEndpoint; 52 | 53 | @Autowired 54 | private ConfigurationPropertiesEndpoint configurationPropertiesEndpoint; 55 | 56 | @Test 57 | void testArtifactsEndpoint() { 58 | assertFalse(artifactsEndpoint.getArtifactMetaInfoList().isEmpty()); 59 | } 60 | 61 | @Test 62 | void testInvokeReadOperations() { 63 | Map aggregatedResults = webEndpoints.invokeReadOperations(); 64 | assertFalse(aggregatedResults.isEmpty()); 65 | } 66 | 67 | @Test 68 | void testGetConfigurationMetadata() { 69 | ConfigurationMetadataEndpoint.ConfigurationMetadataDescriptor configurationMetadata = configurationMetadataEndpoint.getConfigurationMetadata(); 70 | assertFalse(configurationMetadata.getGroups().isEmpty()); 71 | assertFalse(configurationMetadata.getProperties().isEmpty()); 72 | } 73 | 74 | @Test 75 | void testGetConfigurationProperties() { 76 | ConfigurationPropertiesDescriptor descriptor = configurationPropertiesEndpoint.getConfigurationProperties(); 77 | assertNotNull(descriptor); 78 | assertFalse(descriptor.getConfigurationProperties().isEmpty()); 79 | } 80 | 81 | public static void main(String[] args) { 82 | new SpringApplicationBuilder(ActuatorEndpointsAutoConfigurationTest.class) 83 | .web(SERVLET) 84 | .run(args); 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/MonitoredThreadPoolTaskScheduler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.actuate; 18 | 19 | import io.micrometer.core.instrument.MeterRegistry; 20 | import io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics; 21 | import io.microsphere.concurrent.DelegatingScheduledExecutorService; 22 | import org.springframework.beans.BeansException; 23 | import org.springframework.beans.factory.SmartInitializingSingleton; 24 | import org.springframework.context.ApplicationContext; 25 | import org.springframework.context.ApplicationContextAware; 26 | import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; 27 | 28 | import java.util.concurrent.RejectedExecutionHandler; 29 | import java.util.concurrent.ScheduledExecutorService; 30 | import java.util.concurrent.ThreadFactory; 31 | 32 | import static io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics.monitor; 33 | 34 | /** 35 | * {@link ThreadPoolTaskScheduler} with {@link ExecutorServiceMetrics} features 36 | * 37 | * @author Mercy 38 | * @see ThreadPoolTaskScheduler 39 | * @see ExecutorServiceMetrics 40 | * @see io.micrometer.core.instrument.internal.TimedScheduledExecutorService 41 | * @since 1.0.0 42 | */ 43 | public class MonitoredThreadPoolTaskScheduler extends ThreadPoolTaskScheduler implements ApplicationContextAware, SmartInitializingSingleton { 44 | 45 | private String beanName; 46 | 47 | private ApplicationContext context; 48 | 49 | private DelegatingScheduledExecutorService delegate; 50 | 51 | public MonitoredThreadPoolTaskScheduler() { 52 | super(); 53 | } 54 | 55 | @Override 56 | protected ScheduledExecutorService createExecutor(int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) { 57 | ScheduledExecutorService scheduledExecutor = super.createExecutor(poolSize, threadFactory, rejectedExecutionHandler); 58 | this.delegate = new DelegatingScheduledExecutorService(scheduledExecutor); 59 | return scheduledExecutor; 60 | } 61 | 62 | @Override 63 | public ScheduledExecutorService getScheduledExecutor() throws IllegalStateException { 64 | return delegate; 65 | } 66 | 67 | @Override 68 | public void afterSingletonsInstantiated() { 69 | MeterRegistry registry = context.getBean(MeterRegistry.class); 70 | ScheduledExecutorService scheduledExecutor = super.getScheduledExecutor(); 71 | this.delegate.setDelegate(monitor(registry, scheduledExecutor, beanName)); 72 | } 73 | 74 | @Override 75 | public void setBeanName(String name) { 76 | super.setBeanName(name); 77 | this.beanName = name; 78 | } 79 | 80 | @Override 81 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 82 | this.context = applicationContext; 83 | } 84 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/classloading/BannedArtifactClassLoadingListenerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.classloading; 19 | 20 | 21 | import org.junit.jupiter.api.AfterEach; 22 | import org.junit.jupiter.api.BeforeEach; 23 | import org.junit.jupiter.api.Test; 24 | import org.springframework.boot.SpringApplication; 25 | 26 | import java.net.URLClassLoader; 27 | import java.util.Properties; 28 | 29 | import static io.microsphere.spring.boot.classloading.BannedArtifactClassLoadingListener.BANNED_ARTIFACTS_ENABLED_PROPERTY_NAME; 30 | import static io.microsphere.spring.boot.util.TestUtils.application; 31 | import static io.microsphere.util.ArrayUtils.ofArray; 32 | import static java.lang.System.getProperties; 33 | import static java.lang.Thread.currentThread; 34 | import static org.junit.jupiter.api.Assertions.assertFalse; 35 | import static org.junit.jupiter.api.Assertions.assertTrue; 36 | 37 | /** 38 | * {@link BannedArtifactClassLoadingListener} Test 39 | * 40 | * @author Mercy 41 | * @see BannedArtifactClassLoadingListener 42 | * @since 1.0.0 43 | */ 44 | class BannedArtifactClassLoadingListenerTest { 45 | 46 | @BeforeEach 47 | void setUp() { 48 | getProperties().remove(BANNED_ARTIFACTS_ENABLED_PROPERTY_NAME); 49 | } 50 | 51 | @AfterEach 52 | void tearDown() { 53 | getProperties().remove(BANNED_ARTIFACTS_ENABLED_PROPERTY_NAME); 54 | } 55 | 56 | @Test 57 | void testStartingOnDefaults() { 58 | assertListener(application()); 59 | } 60 | 61 | @Test 62 | void testStarting() { 63 | doInEnabled(() -> assertListener(application())); 64 | } 65 | 66 | @Test 67 | void testStartingOnDifferentClassLoader() { 68 | doInEnabled(() -> { 69 | SpringApplication springApplication = application(); 70 | currentThread().setContextClassLoader(new URLClassLoader(ofArray(), null)); 71 | assertListener(springApplication); 72 | }); 73 | } 74 | 75 | void assertListener(SpringApplication application) { 76 | BannedArtifactClassLoadingListener listener = new BannedArtifactClassLoadingListener(application); 77 | assertFalse(listener.isProcessed()); 78 | listener.starting(); 79 | assertTrue(listener.isProcessed()); 80 | listener.starting(); 81 | assertTrue(listener.isProcessed()); 82 | } 83 | 84 | void doInEnabled(Runnable runnable) { 85 | ClassLoader classLoader = currentThread().getContextClassLoader(); 86 | Properties properties = getProperties(); 87 | try { 88 | properties.setProperty(BANNED_ARTIFACTS_ENABLED_PROPERTY_NAME, "true"); 89 | runnable.run(); 90 | } finally { 91 | properties.remove(BANNED_ARTIFACTS_ENABLED_PROPERTY_NAME); 92 | currentThread().setContextClassLoader(classLoader); 93 | } 94 | } 95 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/condition/OnPropertyPrefixConditionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.condition; 19 | 20 | 21 | import io.microsphere.spring.test.context.annotation.TestConditionContext; 22 | import org.junit.jupiter.api.BeforeEach; 23 | import org.junit.jupiter.api.Test; 24 | import org.springframework.boot.autoconfigure.condition.ConditionOutcome; 25 | import org.springframework.context.ConfigurableApplicationContext; 26 | import org.springframework.context.support.GenericApplicationContext; 27 | import org.springframework.core.type.AnnotatedTypeMetadata; 28 | import org.springframework.core.type.StandardMethodMetadata; 29 | import org.springframework.mock.env.MockEnvironment; 30 | 31 | import static io.microsphere.reflect.MethodUtils.findMethod; 32 | import static io.microsphere.spring.boot.constants.PropertyConstants.MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX; 33 | import static org.junit.jupiter.api.Assertions.assertEquals; 34 | 35 | /** 36 | * {@link OnPropertyPrefixCondition} Test 37 | * 38 | * @author Mercy 39 | * @see OnPropertyPrefixCondition 40 | * @since 1.0.0 41 | */ 42 | class OnPropertyPrefixConditionTest { 43 | 44 | private static final String propertyNamePrefix = MICROSPHERE_SPRING_BOOT_PROPERTY_NAME_PREFIX; 45 | 46 | private MockEnvironment environment; 47 | 48 | private TestConditionContext conditionContext; 49 | 50 | private AnnotatedTypeMetadata metadata; 51 | 52 | private OnPropertyPrefixCondition condition; 53 | 54 | @BeforeEach 55 | @ConditionalOnPropertyPrefix(value = propertyNamePrefix) 56 | void setUp() { 57 | this.environment = new MockEnvironment(); 58 | ConfigurableApplicationContext context = new GenericApplicationContext(); 59 | context.setEnvironment(this.environment); 60 | this.conditionContext = new TestConditionContext(); 61 | this.conditionContext.setApplicationContext(context); 62 | this.metadata = new StandardMethodMetadata(findMethod(getClass(), "setUp")); 63 | this.condition = new OnPropertyPrefixCondition(); 64 | } 65 | 66 | @Test 67 | void testGetMatchOutcomeOnMatch() { 68 | String propertyName = propertyNamePrefix + "key"; 69 | this.environment.setProperty(propertyName, "value"); 70 | testGetMatchOutcome(true); 71 | } 72 | 73 | @Test 74 | void testGetMatchOutcomeOnNoMatch() { 75 | String propertyName = "key"; 76 | this.environment.setProperty(propertyName, "value"); 77 | testGetMatchOutcome(false); 78 | } 79 | 80 | @Test 81 | void testGetMatchOutcomeWithoutProperty() { 82 | testGetMatchOutcome(false); 83 | } 84 | 85 | void testGetMatchOutcome(boolean matched) { 86 | ConditionOutcome outcome = this.condition.getMatchOutcome(conditionContext, metadata); 87 | assertEquals(matched, outcome.isMatch()); 88 | } 89 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/listener/LoggingSpringApplicationRunListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.listener; 19 | 20 | import io.microsphere.spring.boot.util.SpringApplicationUtils; 21 | import org.springframework.boot.ConfigurableBootstrapContext; 22 | import org.springframework.boot.SpringApplication; 23 | import org.springframework.boot.SpringApplicationRunListener; 24 | import org.springframework.context.ConfigurableApplicationContext; 25 | import org.springframework.core.env.ConfigurableEnvironment; 26 | 27 | import static io.microsphere.spring.boot.util.SpringApplicationUtils.log; 28 | 29 | /** 30 | * {@link SpringApplicationRunListener} class for logging based on {@link SpringApplicationRunListenerAdapter} 31 | * 32 | * @author Mercy 33 | * @see SpringApplicationRunListenerAdapter 34 | * @see SpringApplicationRunListener 35 | * @see SpringApplicationUtils 36 | * @since 1.0.0 37 | */ 38 | public class LoggingSpringApplicationRunListener extends SpringApplicationRunListenerAdapter { 39 | 40 | public LoggingSpringApplicationRunListener(SpringApplication springApplication, String[] args) { 41 | super(springApplication, args); 42 | } 43 | 44 | @Override 45 | public void starting(ConfigurableBootstrapContext bootstrapContext) { 46 | super.starting(bootstrapContext); 47 | log(getSpringApplication(), getArgs(), "starting... : {}", bootstrapContext); 48 | } 49 | 50 | @Override 51 | public void starting() { 52 | super.starting(); 53 | log(getSpringApplication(), getArgs(), "starting..."); 54 | } 55 | 56 | @Override 57 | public void environmentPrepared(ConfigurableEnvironment environment) { 58 | super.environmentPrepared(environment); 59 | log(getSpringApplication(), getArgs(), "environmentPrepared : {}", environment); 60 | 61 | } 62 | 63 | @Override 64 | public void contextPrepared(ConfigurableApplicationContext context) { 65 | super.contextPrepared(context); 66 | log(getSpringApplication(), getArgs(), context, "contextPrepared : {}", context); 67 | 68 | } 69 | 70 | @Override 71 | public void contextLoaded(ConfigurableApplicationContext context) { 72 | super.contextLoaded(context); 73 | log(getSpringApplication(), getArgs(), context, "contextLoaded : {}", context); 74 | } 75 | 76 | @Override 77 | public void started(ConfigurableApplicationContext context) { 78 | super.started(context); 79 | log(getSpringApplication(), getArgs(), context, "started : {}", context); 80 | 81 | } 82 | 83 | @Override 84 | public void running(ConfigurableApplicationContext context) { 85 | super.running(context); 86 | log(getSpringApplication(), getArgs(), context, "running : {}", context); 87 | } 88 | 89 | @Override 90 | public void failed(ConfigurableApplicationContext context, Throwable exception) { 91 | super.failed(context, exception); 92 | log(getSpringApplication(), getArgs(), context, "failed : {}", exception); 93 | } 94 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/ListenableConfigurationPropertiesBindHandlerAdvisor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties; 18 | 19 | import io.microsphere.spring.boot.context.properties.bind.BindListener; 20 | import io.microsphere.spring.boot.context.properties.bind.ListenableBindHandlerAdapter; 21 | import org.springframework.beans.BeansException; 22 | import org.springframework.beans.factory.BeanFactory; 23 | import org.springframework.beans.factory.BeanFactoryAware; 24 | import org.springframework.boot.context.properties.ConfigurationPropertiesBindHandlerAdvisor; 25 | import org.springframework.boot.context.properties.bind.BindHandler; 26 | import org.springframework.boot.context.properties.bind.Bindable; 27 | import org.springframework.boot.context.properties.bind.Binder; 28 | 29 | import java.util.List; 30 | 31 | import static io.microsphere.spring.beans.BeanUtils.getSortedBeans; 32 | 33 | /** 34 | * {@link ConfigurationPropertiesBindHandlerAdvisor} supports the chaining of the {@link BindListener BindListeners' beans} 35 | * 36 | *

Example Usage

37 | *
{@code
38 |  * @Component
39 |  * public class MyBindListener implements BindListener {
40 |  *
41 |  *     @Override
42 |  *     public void onStart(ConfigurationPropertyName name, Bindable target, BindContext context) {
43 |  *         System.out.println("Binding started for: " + name);
44 |  *     }
45 |  *
46 |  *     @Override
47 |  *     public Object onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) {
48 |  *         System.out.println("Binding succeeded for: " + name);
49 |  *         return result;
50 |  *     }
51 |  *
52 |  *     @Override
53 |  *     public Object onFailure(ConfigurationPropertyName name, Bindable target, BindContext context, Exception error) {
54 |  *         System.out.println("Binding failed for: " + name + ", error: " + error.getMessage());
55 |  *         return null;
56 |  *     }
57 |  * }
58 |  * }
59 | * 60 | *

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

65 | * 66 | * @author Mercy 67 | * @see ConfigurationPropertiesBindHandlerAdvisor 68 | * @see BindHandler 69 | * @see Binder 70 | * @see Bindable 71 | * @since 1.0.0 72 | */ 73 | public class ListenableConfigurationPropertiesBindHandlerAdvisor implements ConfigurationPropertiesBindHandlerAdvisor, BeanFactoryAware { 74 | 75 | private BeanFactory beanFactory; 76 | 77 | @Override 78 | public BindHandler apply(BindHandler bindHandler) { 79 | List bindListeners = getSortedBeans(this.beanFactory, BindListener.class); 80 | return new ListenableBindHandlerAdapter(bindHandler, bindListeners); 81 | } 82 | 83 | @Override 84 | public void setBeanFactory(BeanFactory beanFactory) throws BeansException { 85 | this.beanFactory = beanFactory; 86 | } 87 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/ListenableBindHandlerAdapter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.bind; 18 | 19 | import io.microsphere.spring.boot.context.properties.ListenableConfigurationPropertiesBindHandlerAdvisor; 20 | import org.springframework.boot.context.properties.bind.AbstractBindHandler; 21 | import org.springframework.boot.context.properties.bind.BindContext; 22 | import org.springframework.boot.context.properties.bind.BindHandler; 23 | import org.springframework.boot.context.properties.bind.Bindable; 24 | import org.springframework.boot.context.properties.bind.Binder; 25 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 26 | 27 | /** 28 | * Listable {@link BindHandler} Adapter 29 | * 30 | * @author Mercy 31 | * @see ListenableConfigurationPropertiesBindHandlerAdvisor 32 | * @see BindHandler 33 | * @see Binder 34 | * @see Bindable 35 | * @since 1.0.0 36 | */ 37 | public class ListenableBindHandlerAdapter extends AbstractBindHandler { 38 | 39 | private final BindListeners bindHandlers; 40 | 41 | public ListenableBindHandlerAdapter(Iterable bindListeners) { 42 | this(DEFAULT, bindListeners); 43 | } 44 | 45 | public ListenableBindHandlerAdapter(BindHandler parent, Iterable bindListeners) { 46 | super(parent); 47 | this.bindHandlers = new BindListeners(bindListeners); 48 | } 49 | 50 | @Override 51 | public Bindable onStart(ConfigurationPropertyName name, Bindable target, BindContext context) { 52 | Bindable result = super.onStart(name, target, context); 53 | bindHandlers.onStart(name, target, context); 54 | return result; 55 | } 56 | 57 | @Override 58 | public Object onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 59 | Object returnValue = super.onSuccess(name, target, context, result); 60 | bindHandlers.onSuccess(name, target, context, result); 61 | return returnValue; 62 | } 63 | 64 | @Override 65 | public Object onCreate(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 66 | Object returnValue = super.onCreate(name, target, context, result); 67 | bindHandlers.onCreate(name, target, context, result); 68 | return returnValue; 69 | } 70 | 71 | @Override 72 | public Object onFailure(ConfigurationPropertyName name, Bindable target, BindContext context, Exception error) throws Exception { 73 | try { 74 | return super.onFailure(name, target, context, error); 75 | } catch (Exception e) { 76 | bindHandlers.onFailure(name, target, context, error); 77 | throw e; 78 | } 79 | } 80 | 81 | @Override 82 | public void onFinish(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) throws Exception { 83 | super.onFinish(name, target, context, result); 84 | bindHandlers.onFinish(name, target, context, result); 85 | } 86 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/source/util/ConfigurationPropertyUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.source.util; 18 | 19 | import org.springframework.boot.context.properties.bind.BindContext; 20 | import org.springframework.boot.context.properties.bind.DataObjectPropertyName; 21 | import org.springframework.boot.context.properties.source.ConfigurationProperty; 22 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 23 | 24 | import static io.microsphere.constants.SymbolConstants.DOT; 25 | import static io.microsphere.util.StringUtils.substringBeforeLast; 26 | 27 | /** 28 | * The utilities class of {@link ConfigurationProperty} 29 | * 30 | * @author Mercy 31 | * @see ConfigurationProperty 32 | * @since 1.0.0 33 | */ 34 | public abstract class ConfigurationPropertyUtils { 35 | 36 | /** 37 | * Get the prefix of the specified {@link ConfigurationPropertyName} 38 | * 39 | *

Example Usage

40 | *
{@code
41 |      * ConfigurationPropertyName name = ConfigurationPropertyName.of("server.port");
42 |      * BindContext context = ...; // assume depth = 0
43 |      * String prefix = getPrefix(name, context); // returns "server.port"
44 |      *
45 |      * ConfigurationPropertyName name2 = ConfigurationPropertyName.of("spring.datasource.url");
46 |      * BindContext context2 = ...; // assume depth = 1
47 |      * String prefix2 = getPrefix(name2, context2); // returns "spring.datasource"
48 |      * }
49 | * 50 | * @param name the {@link ConfigurationPropertyName} 51 | * @param context the {@link BindContext} 52 | * @return the prefix of the specified {@link ConfigurationPropertyName} 53 | * @throws IllegalArgumentException if name or context is null 54 | */ 55 | public static final String getPrefix(ConfigurationPropertyName name, BindContext context) { 56 | int depth = context.getDepth(); 57 | String propertyName = name.toString(); 58 | String prefix = propertyName; 59 | for (int i = 0; i < depth; i++) { 60 | prefix = substringBeforeLast(prefix, DOT); 61 | } 62 | return prefix; 63 | } 64 | 65 | /** 66 | * Return the specified Java Bean property name in dashed form. 67 | * 68 | *

Example Usage

69 | *
{@code
70 |      * String result1 = toDashedForm("userName");     // returns "user-name"
71 |      * String result2 = toDashedForm("firstName");    // returns "first-name"
72 |      * String result3 = toDashedForm("URL");          // returns "url"
73 |      * String result4 = toDashedForm("myURL");        // returns "my-url"
74 |      * String result5 = toDashedForm("user_name");    // returns "user-name"
75 |      * }
76 | * 77 | * @param name the source name 78 | * @return the dashed from 79 | * @see org.springframework.boot.context.properties.bind.DataObjectPropertyName#toDashedForm(String) 80 | */ 81 | public static String toDashedForm(String name) { 82 | return DataObjectPropertyName.toDashedForm(name); 83 | } 84 | 85 | private ConfigurationPropertyUtils() { 86 | } 87 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/util/ConfigurationPropertiesUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.util; 18 | 19 | import org.springframework.boot.context.properties.ConfigurationProperties; 20 | import org.springframework.boot.context.properties.bind.Bindable; 21 | import org.springframework.core.ResolvableType; 22 | 23 | import static io.microsphere.util.AnnotationUtils.findAnnotation; 24 | 25 | /** 26 | * The utilities class of {@link ConfigurationProperties} 27 | * 28 | * @author Mercy 29 | * @see ConfigurationProperties 30 | * @since 1.0.0 31 | */ 32 | public abstract class ConfigurationPropertiesUtils { 33 | 34 | /** 35 | * The {@link Class} of {@link ConfigurationProperties} 36 | */ 37 | public static final Class CONFIGURATION_PROPERTIES_CLASS = ConfigurationProperties.class; 38 | 39 | /** 40 | * Find an annotation of {@link ConfigurationProperties} from the specified {@link Bindable}. 41 | * 42 | *

Example Usage

43 | *
{@code
44 |      * @ConfigurationProperties(prefix = "app.config")
45 |      * public class AppConfig {
46 |      *     private String name;
47 |      *     // getters and setters
48 |      * }
49 |      *
50 |      * Bindable bindable = Bindable.of(AppConfig.class);
51 |      * ConfigurationProperties props = ConfigurationPropertiesUtils.findConfigurationProperties(bindable);
52 |      * // props will contain the annotation with prefix "app.config"
53 |      * }
54 | * 55 | *

Another example with nested properties

56 | *
{@code
57 |      * public class ParentConfig {
58 |      *     @ConfigurationProperties(prefix = "parent.child")
59 |      *     private ChildConfig child;
60 |      *     // getters and setters
61 |      * }
62 |      *
63 |      * Bindable bindable = Bindable.of(ChildConfig.class);
64 |      * ConfigurationProperties props = ConfigurationPropertiesUtils.findConfigurationProperties(bindable);
65 |      * // props will contain the annotation with prefix "parent.child"
66 |      * }
67 | * 68 | * @param bindable {@link Bindable} 69 | * @return an annotation of {@link ConfigurationProperties} if present 70 | * @throws NullPointerException if bindable is null 71 | * @since 1.0.0 72 | */ 73 | public static ConfigurationProperties findConfigurationProperties(Bindable bindable) { 74 | // Find an annotation of @ConfigurationProperties from annotations 75 | ConfigurationProperties configurationProperties = (ConfigurationProperties) bindable.getAnnotation(CONFIGURATION_PROPERTIES_CLASS); 76 | if (configurationProperties == null) { 77 | // If not found, try to find an annotation of @ConfigurationProperties from the bindable's type 78 | ResolvableType type = bindable.getType(); 79 | Class bindableType = type.resolve(); 80 | configurationProperties = findAnnotation(bindableType, CONFIGURATION_PROPERTIES_CLASS); 81 | } 82 | return configurationProperties; 83 | } 84 | 85 | private ConfigurationPropertiesUtils() { 86 | } 87 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-parent/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | io.github.microsphere-projects 7 | microsphere-spring-boot 8 | ${revision} 9 | ../pom.xml 10 | 11 | 4.0.0 12 | 13 | io.github.microsphere-projects 14 | microsphere-spring-boot-parent 15 | ${revision} 16 | pom 17 | 18 | Microsphere :: Spring Boot :: Parent 19 | Microsphere Spring Boot Parent 20 | 21 | 22 | 0.2.5 23 | 1.7.2 24 | 25 | 26 | 27 | 28 | 29 | 30 | org.springframework.boot 31 | spring-boot-dependencies 32 | ${spring-boot.version} 33 | pom 34 | import 35 | 36 | 37 | 38 | 39 | io.github.microsphere-projects 40 | microsphere-spring-dependencies 41 | ${microsphere-spring.version} 42 | pom 43 | import 44 | 45 | 46 | 47 | 48 | 49 | 50 | spring-milestone 51 | Spring Portfolio Milestone Repository 52 | https://repo.spring.io/milestone 53 | 54 | 55 | 56 | 57 | 58 | spring-boot-3.0 59 | 60 | 3.0.13 61 | 62 | 63 | 64 | 65 | spring-boot-3.1 66 | 67 | 3.1.12 68 | 69 | 70 | 71 | 72 | spring-boot-3.2 73 | 74 | 3.2.12 75 | 76 | 77 | 78 | 79 | spring-boot-3.3 80 | 81 | 3.3.13 82 | 83 | 84 | 85 | 86 | spring-boot-3.4 87 | 88 | 3.4.11 89 | 90 | 91 | 92 | 93 | spring-boot-3.5 94 | 95 | true 96 | 97 | 98 | 3.5.7 99 | 100 | 101 | 102 | 103 | spring-boot-4.0 104 | 105 | 4.0.0-RC2 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | io.github.microsphere-projects 7 | microsphere-spring-boot-parent 8 | ${revision} 9 | ../microsphere-spring-boot-parent/pom.xml 10 | 11 | 4.0.0 12 | 13 | io.github.microsphere-projects 14 | microsphere-spring-boot-core 15 | ${revision} 16 | 17 | Microsphere :: Spring Boot :: Core 18 | Microsphere Spring Boot Core 19 | 20 | 21 | 22 | 23 | io.github.microsphere-projects 24 | microsphere-java-core 25 | 26 | 27 | 28 | io.github.microsphere-projects 29 | microsphere-annotation-processor 30 | true 31 | 32 | 33 | 34 | io.github.microsphere-projects 35 | microsphere-spring-context 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter 42 | true 43 | 44 | 45 | 46 | org.springframework.boot 47 | spring-boot-configuration-processor 48 | true 49 | 50 | 51 | 52 | 53 | org.junit.jupiter 54 | junit-jupiter 55 | test 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-starter-test 61 | test 62 | 63 | 64 | 65 | io.github.microsphere-projects 66 | microsphere-spring-test 67 | test 68 | 69 | 70 | org.apache.zookeeper 71 | zookeeper 72 | 73 | 74 | org.apache.curator 75 | curator-recipes 76 | 77 | 78 | org.apache.curator 79 | curator-test 80 | 81 | 82 | 83 | 84 | 85 | org.springframework.boot 86 | spring-boot-starter-web 87 | test 88 | 89 | 90 | 91 | org.springframework.boot 92 | spring-boot-loader 93 | test 94 | 95 | 96 | 97 | jakarta.annotation 98 | jakarta.annotation-api 99 | test 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/test/java/io/microsphere/spring/boot/actuate/env/DefaultPropertiesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.actuate.env; 18 | 19 | import io.microsphere.spring.boot.env.SpringApplicationDefaultPropertiesPostProcessor; 20 | import org.junit.jupiter.api.Test; 21 | import org.junit.jupiter.api.extension.ExtendWith; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.boot.test.context.SpringBootTest; 24 | import org.springframework.core.env.Environment; 25 | import org.springframework.test.context.junit.jupiter.SpringExtension; 26 | 27 | import static org.junit.jupiter.api.Assertions.assertEquals; 28 | 29 | /** 30 | * Spring Boot Default Properties Test 31 | * 32 | * @author Mercy 33 | * @see SpringApplicationDefaultPropertiesPostProcessor 34 | * @since 1.0.0 35 | */ 36 | @ExtendWith(SpringExtension.class) 37 | @SpringBootTest(classes = {DefaultPropertiesTest.class}) 38 | class DefaultPropertiesTest { 39 | 40 | @Autowired 41 | private Environment environment; 42 | 43 | @Test 44 | void testEndpointsDefaultProperties() { 45 | assertProperty("management.endpoints.enabled-by-default", "false"); 46 | assertProperty("management.endpoints.web.exposure.include", "*"); 47 | assertProperty("management.endpoints.jmx.exposure.exclude", "*"); 48 | 49 | assertProperty("management.endpoint.auditevents.enabled", "false"); 50 | assertProperty("management.endpoint.beans.enabled", "false"); 51 | assertProperty("management.endpoint.caches.enabled", "false"); 52 | assertProperty("management.endpoint.conditions.enabled", "false"); 53 | assertProperty("management.endpoint.configprops.enabled", "false"); 54 | assertProperty("management.endpoint.env.enabled", "true"); 55 | assertProperty("management.endpoint.flyway.enabled", "false"); 56 | assertProperty("management.endpoint.health.enabled", "true"); 57 | assertProperty("management.endpoint.httptrace.enabled", "false"); 58 | assertProperty("management.endpoint.info.enabled", "true"); 59 | assertProperty("management.endpoint.integrationgraph.enabled", "false"); 60 | assertProperty("management.endpoint.loggers.enabled", "false"); 61 | assertProperty("management.endpoint.liquibase.enabled", "false"); 62 | assertProperty("management.endpoint.metrics.enabled", "true"); 63 | assertProperty("management.endpoint.mappings.enabled", "true"); 64 | assertProperty("management.endpoint.scheduledtasks.enabled", "false"); 65 | assertProperty("management.endpoint.sessions.enabled", "false"); 66 | assertProperty("management.endpoint.shutdown.enabled", "false"); 67 | assertProperty("management.endpoint.threaddump.enabled", "false"); 68 | assertProperty("management.endpoint.heapdump.enabled", "false"); 69 | assertProperty("management.endpoint.jolokia.enabled", "true"); 70 | assertProperty("management.endpoint.logfile.enabled", "false"); 71 | assertProperty("management.endpoint.prometheus.enabled", "true"); 72 | 73 | 74 | } 75 | 76 | private void assertProperty(String propertyName, String expectedValue) { 77 | assertEquals(expectedValue, environment.getRequiredProperty(propertyName)); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/config/BindableConfigurationBeanBinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.config; 18 | 19 | import io.microsphere.spring.context.config.ConfigurationBeanBinder; 20 | import io.microsphere.spring.context.config.DefaultConfigurationBeanBinder; 21 | import org.springframework.boot.context.properties.bind.BindHandler; 22 | import org.springframework.boot.context.properties.bind.Bindable; 23 | import org.springframework.boot.context.properties.bind.Binder; 24 | import org.springframework.boot.context.properties.bind.PropertySourcesPlaceholdersResolver; 25 | import org.springframework.boot.context.properties.source.ConfigurationPropertySource; 26 | import org.springframework.core.convert.ConversionService; 27 | import org.springframework.core.env.MapPropertySource; 28 | import org.springframework.core.env.PropertySource; 29 | 30 | import java.util.Map; 31 | 32 | import static io.microsphere.collection.Lists.ofList; 33 | import static io.microsphere.spring.boot.context.properties.bind.util.BindHandlerUtils.createBindHandler; 34 | import static io.microsphere.util.StringUtils.EMPTY_STRING; 35 | import static org.springframework.boot.context.properties.bind.Bindable.ofInstance; 36 | import static org.springframework.boot.context.properties.source.ConfigurationPropertySources.from; 37 | 38 | /** 39 | * A {@link ConfigurationBeanBinder} implementation based on Spring Boot 2's {@link Binder}, 40 | * which binds configuration properties to a given bean using {@link Bindable}. 41 | * 42 | *

Example Usage

43 | *
{@code
44 |  *     Map properties = new HashMap<>();
45 |  *     properties.put("app.name", "demo");
46 |  *     MyConfigBean bean = new MyConfigBean();
47 |  *     BindableConfigurationBeanBinder binder = new BindableConfigurationBeanBinder();
48 |  *     binder.bind(properties, true, true, bean);
49 |  *     // bean.getAppName() == "demo"
50 |  * }
51 | * 52 | * @author
Mercy 53 | * @see DefaultConfigurationBeanBinder 54 | * @see ConfigurationBeanBinder 55 | * @since 1.0.0 56 | */ 57 | public class BindableConfigurationBeanBinder implements ConfigurationBeanBinder { 58 | 59 | private ConversionService conversionService; 60 | 61 | @Override 62 | public void setConversionService(ConversionService conversionService) { 63 | this.conversionService = conversionService; 64 | } 65 | 66 | @Override 67 | public void bind(Map configurationProperties, boolean ignoreUnknownFields, 68 | boolean ignoreInvalidFields, Object configurationBean) { 69 | 70 | Iterable> propertySources = ofList(new MapPropertySource("internal", configurationProperties)); 71 | 72 | // Converts ConfigurationPropertySources 73 | Iterable configurationPropertySources = from(propertySources); 74 | 75 | // Wrap Bindable from configuration bean 76 | Bindable bindable = ofInstance(configurationBean); 77 | 78 | Binder binder = new Binder(configurationPropertySources, new PropertySourcesPlaceholdersResolver(propertySources), conversionService); 79 | 80 | // Get BindHandler 81 | BindHandler bindHandler = createBindHandler(ignoreUnknownFields, ignoreInvalidFields); 82 | 83 | // Bind 84 | binder.bind(EMPTY_STRING, bindable, bindHandler); 85 | } 86 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/bind/BindListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.bind; 18 | 19 | import org.springframework.boot.context.properties.bind.BindContext; 20 | import org.springframework.boot.context.properties.bind.BindHandler; 21 | import org.springframework.boot.context.properties.bind.Bindable; 22 | import org.springframework.boot.context.properties.source.ConfigurationPropertyName; 23 | 24 | /** 25 | * Bind Listener 26 | * 27 | * @author Mercy 28 | * @see BindHandler 29 | * @since 1.0.0 30 | */ 31 | public interface BindListener { 32 | 33 | /** 34 | * Called when binding of an element starts but before any result has been determined. 35 | * 36 | * @param name the name of the element being bound 37 | * @param target the item being bound 38 | * @param context the bind context 39 | */ 40 | default void onStart(ConfigurationPropertyName name, Bindable target, BindContext context) { 41 | } 42 | 43 | /** 44 | * Called when binding of an element ends with a successful result. Implementations 45 | * may change the ultimately returned result or perform addition validation. 46 | * 47 | * @param name the name of the element being bound 48 | * @param target the item being bound 49 | * @param context the bind context 50 | * @param result the bound result (never {@code null}) 51 | */ 52 | default void onSuccess(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 53 | } 54 | 55 | /** 56 | * Called when binding of an element ends with an unbound result and a newly created 57 | * instance is about to be returned. Implementations may change the ultimately 58 | * returned result or perform addition validation. 59 | * 60 | * @param name the name of the element being bound 61 | * @param target the item being bound 62 | * @param context the bind context 63 | * @param result the newly created instance (never {@code null}) 64 | */ 65 | default void onCreate(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 66 | } 67 | 68 | /** 69 | * Called when binding fails for any reason (including failures from 70 | * {@link #onSuccess} Implementations may choose to 71 | * swallow exceptions and return an alternative result. 72 | * 73 | * @param name the name of the element being bound 74 | * @param target the item being bound 75 | * @param context the bind context 76 | * @param error the cause of the error (if the exception stands it may be re-thrown) 77 | */ 78 | default void onFailure(ConfigurationPropertyName name, Bindable target, BindContext context, Exception error) { 79 | } 80 | 81 | /** 82 | * Called when binding finishes with either bound or unbound result. This method will 83 | * not be called when binding failed, even if a handler returns a result from 84 | * {@link #onFailure}. 85 | * 86 | * @param name the name of the element being bound 87 | * @param target the item being bound 88 | * @param context the bind context 89 | * @param result the bound result (may be {@code null}) 90 | */ 91 | default void onFinish(ConfigurationPropertyName name, Bindable target, BindContext context, Object result) { 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/test/java/io/microsphere/spring/boot/context/properties/ConfigurationPropertiesBeanInfoTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package io.microsphere.spring.boot.context.properties; 19 | 20 | 21 | import org.junit.jupiter.api.BeforeEach; 22 | import org.junit.jupiter.api.Test; 23 | import org.springframework.boot.autoconfigure.web.ServerProperties; 24 | import org.springframework.boot.autoconfigure.web.servlet.MultipartProperties; 25 | import org.springframework.boot.context.properties.ConfigurationProperties; 26 | 27 | import java.beans.PropertyDescriptor; 28 | import java.util.List; 29 | 30 | import static io.microsphere.spring.boot.context.properties.util.ConfigurationPropertiesUtils.CONFIGURATION_PROPERTIES_CLASS; 31 | import static org.junit.jupiter.api.Assertions.assertEquals; 32 | import static org.junit.jupiter.api.Assertions.assertFalse; 33 | import static org.junit.jupiter.api.Assertions.assertNotEquals; 34 | import static org.junit.jupiter.api.Assertions.assertSame; 35 | import static org.springframework.util.StringUtils.hasText; 36 | 37 | /** 38 | * {@link ConfigurationPropertiesBeanInfo} Test 39 | * 40 | * @author Mercy 41 | * @see ConfigurationPropertiesBeanInfo 42 | * @since 1.0.0 43 | */ 44 | @ConfigurationProperties(prefix = "server") 45 | class ConfigurationPropertiesBeanInfoTest { 46 | 47 | private ConfigurationPropertiesBeanInfo info; 48 | 49 | @BeforeEach 50 | void setUp() { 51 | this.info = new ConfigurationPropertiesBeanInfo(ServerProperties.class); 52 | } 53 | 54 | @Test 55 | void testGetBeanClass() { 56 | assertSame(ServerProperties.class, this.info.getBeanClass()); 57 | } 58 | 59 | @Test 60 | void testGetAnnotation() { 61 | ConfigurationProperties configurationProperties = this.info.getAnnotation(); 62 | assertEquals("server", hasText(configurationProperties.prefix()) ? 63 | configurationProperties.prefix() : configurationProperties.value()); 64 | } 65 | 66 | @Test 67 | void testGetPrefix() { 68 | assertEquals("server", this.info.getPrefix()); 69 | assertEquals("spring.servlet.multipart", new ConfigurationPropertiesBeanInfo(MultipartProperties.class).getPrefix()); 70 | } 71 | 72 | @Test 73 | void testGetPropertyDescriptors() { 74 | List descriptors = this.info.getPropertyDescriptors(); 75 | assertFalse(descriptors.isEmpty()); 76 | } 77 | 78 | @Test 79 | void testGetPropertyDescriptor() { 80 | String name = "port"; 81 | PropertyDescriptor portPropertyDescriptor = this.info.getPropertyDescriptor(name); 82 | assertEquals(name, portPropertyDescriptor.getName()); 83 | } 84 | 85 | @Test 86 | void testEquals() { 87 | assertEquals(this.info, this.info); 88 | assertEquals(this.info, new ConfigurationPropertiesBeanInfo(ServerProperties.class)); 89 | assertNotEquals(this.info, this); 90 | assertNotEquals(this.info, new ConfigurationPropertiesBeanInfo(ConfigurationPropertiesBeanInfoTest.class)); 91 | assertNotEquals(this.info, new ConfigurationPropertiesBeanInfo(ServerProperties.class, 92 | ServerProperties.class.getAnnotation(CONFIGURATION_PROPERTIES_CLASS), "server-1")); 93 | } 94 | 95 | @Test 96 | void testHashCode() { 97 | assertEquals(this.info.hashCode(), new ConfigurationPropertiesBeanInfo(ServerProperties.class).hashCode()); 98 | } 99 | 100 | @Test 101 | void testToString() { 102 | assertEquals(this.info.toString(), new ConfigurationPropertiesBeanInfo(ServerProperties.class).toString()); 103 | } 104 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceMainApplicationPreparedEventListener.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.context; 2 | 3 | import io.microsphere.annotation.Nonnull; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 6 | import org.springframework.context.ApplicationContext; 7 | import org.springframework.context.ApplicationListener; 8 | import org.springframework.context.ConfigurableApplicationContext; 9 | import org.springframework.core.env.ConfigurableEnvironment; 10 | 11 | import static org.springframework.util.ClassUtils.isPresent; 12 | 13 | 14 | /** 15 | * Once execution {@link ApplicationPreparedEvent} {@link ApplicationListener} for Main {@link ApplicationContext}. 16 | *

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

Example Usage

22 | *
{@code
23 |  * public class MyMainApplicationListener extends OnceMainApplicationPreparedEventListener {
24 |  *
25 |  *     @Override
26 |  *     protected void onMainApplicationPrepared(SpringApplication springApplication, String[] args,
27 |  *                                              ConfigurableApplicationContext context) {
28 |  *         // Your custom logic here - this will only execute for the main application context
29 |  *         System.out.println("Main application context is prepared: " + context.getApplicationName());
30 |  *     }
31 |  * }
32 |  * }
33 | * 34 | * @author Mercy 35 | * @see OnceApplicationPreparedEventListener 36 | * @since 1.0.0 37 | */ 38 | public abstract class OnceMainApplicationPreparedEventListener extends OnceApplicationPreparedEventListener { 39 | 40 | /** 41 | * The class name for {@link org.springframework.cloud.bootstrap.BootstrapApplicationListener} 42 | */ 43 | static final String BOOTSTRAP_APPLICATION_LISTENER_CLASS_NAME = "org.springframework.cloud.bootstrap.BootstrapApplicationListener"; 44 | 45 | /** 46 | * The property name for bootstrap {@link ApplicationContext context} {@link ConfigurableApplicationContext#getId() id} 47 | */ 48 | static final String BOOTSTRAP_CONTEXT_ID_PROPERTY_NAME = "spring.cloud.bootstrap.name"; 49 | 50 | /** 51 | * The default bootstrap {@link ApplicationContext context} {@link ConfigurableApplicationContext#getId() id} : "bootstrap" 52 | */ 53 | static final String DEFAULT_BOOTSTRAP_CONTEXT_ID = "bootstrap"; 54 | 55 | protected final boolean isIgnored(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context) { 56 | return isIgnored(context); 57 | } 58 | 59 | protected boolean isIgnored(ConfigurableApplicationContext context) { 60 | if (isBootstrapApplicationListenerPresent(context)) { 61 | return isBootstrapContext(context) || !isMainApplicationContext(context); 62 | } 63 | return false; 64 | } 65 | 66 | boolean isBootstrapContext(ConfigurableApplicationContext context) { 67 | return getBootstrapContextId(context).equals(context.getId()); 68 | } 69 | 70 | boolean isMainApplicationContext(ConfigurableApplicationContext context) { 71 | boolean main = true; 72 | String parentId = null; 73 | ApplicationContext parentContext = context.getParent(); 74 | if (parentContext instanceof ConfigurableApplicationContext) { 75 | parentId = parentContext.getId(); 76 | main = isBootstrapContext((ConfigurableApplicationContext) parentContext); 77 | } 78 | 79 | logger.trace("Current ApplicationContext[id : '{}' , parentId : '{}'] is {}main ApplicationContext", 80 | context.getId(), parentId, main ? "" : "not "); 81 | 82 | return main; 83 | } 84 | 85 | @Nonnull 86 | String getBootstrapContextId(ConfigurableApplicationContext context) { 87 | return getBootstrapContextId(context.getEnvironment()); 88 | } 89 | 90 | @Nonnull 91 | String getBootstrapContextId(ConfigurableEnvironment environment) { 92 | return environment.getProperty(BOOTSTRAP_CONTEXT_ID_PROPERTY_NAME, DEFAULT_BOOTSTRAP_CONTEXT_ID); 93 | } 94 | 95 | private boolean isBootstrapApplicationListenerPresent(ConfigurableApplicationContext context) { 96 | ClassLoader classLoader = context.getClassLoader(); 97 | return isPresent(BOOTSTRAP_APPLICATION_LISTENER_CLASS_NAME, classLoader); 98 | } 99 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-actuator/src/main/java/io/microsphere/spring/boot/actuate/endpoint/WebEndpoints.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.actuate.endpoint; 2 | 3 | import org.springframework.boot.actuate.endpoint.InvocationContext; 4 | import org.springframework.boot.actuate.endpoint.OperationType; 5 | import org.springframework.boot.actuate.endpoint.annotation.AbstractDiscoveredOperation; 6 | import org.springframework.boot.actuate.endpoint.annotation.DiscoveredEndpoint; 7 | import org.springframework.boot.actuate.endpoint.annotation.Endpoint; 8 | import org.springframework.boot.actuate.endpoint.annotation.ReadOperation; 9 | import org.springframework.boot.actuate.endpoint.invoke.reflect.OperationMethod; 10 | import org.springframework.boot.actuate.endpoint.web.ExposableWebEndpoint; 11 | import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoint; 12 | import org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints; 13 | import org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; 14 | import org.springframework.boot.actuate.endpoint.web.WebOperation; 15 | import org.springframework.boot.actuate.endpoint.web.annotation.WebEndpoint; 16 | 17 | import java.lang.reflect.Method; 18 | import java.util.Collection; 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | import static java.util.Collections.emptyMap; 23 | import static org.springframework.boot.actuate.endpoint.OperationType.READ; 24 | import static org.springframework.boot.actuate.endpoint.SecurityContext.NONE; 25 | 26 | /** 27 | * An aggregation {@link WebEndpoint @WebEndpoint} for all {@link WebEndpoint WebEndpoints} 28 | * 29 | * @author Mercy 30 | * @see Endpoint 31 | * @see WebEndpoint 32 | * @see PathMappedEndpoint 33 | * @see PathMappedEndpoints 34 | * @since 1.0.0 35 | */ 36 | @WebEndpoint(id = "webEndpoints") 37 | public class WebEndpoints { 38 | 39 | private final WebEndpointsSupplier webEndpointsSupplier; 40 | 41 | public WebEndpoints(WebEndpointsSupplier webEndpointsSupplier) { 42 | this.webEndpointsSupplier = webEndpointsSupplier; 43 | } 44 | 45 | /** 46 | * all {@link OperationType#READ Read Opeartion} {@link WebEndpoint WebEndpoints} for Java {@link Method} without arguments 47 | * 48 | * @return 49 | */ 50 | @ReadOperation 51 | public Map invokeReadOperations() { 52 | Collection webEndpoints = this.webEndpointsSupplier.getEndpoints(); 53 | 54 | Map readWebOperationResults = new HashMap<>(webEndpoints.size()); 55 | 56 | InvocationContext context = createInvocationContext(); 57 | 58 | for (ExposableWebEndpoint webEndpoint : webEndpoints) { 59 | if (isExposableWebEndpoint(webEndpoint)) { 60 | DiscoveredEndpoint discoveredEndpoint = (DiscoveredEndpoint) webEndpoint; 61 | Object endpointBean = discoveredEndpoint.getEndpointBean(); 62 | if (endpointBean == this) { // ignore self 63 | continue; 64 | } 65 | 66 | Collection webOperations = webEndpoint.getOperations(); 67 | for (WebOperation webOperation : webOperations) { 68 | if (isReadWebOperationCandidate(webOperation)) { 69 | String readWebOperationId = webOperation.getId(); 70 | Object readWebOperationResult = webOperation.invoke(context); 71 | readWebOperationResults.put(readWebOperationId, readWebOperationResult); 72 | } 73 | } 74 | } 75 | } 76 | 77 | return readWebOperationResults; 78 | } 79 | 80 | private InvocationContext createInvocationContext() { 81 | return new InvocationContext(NONE, emptyMap()); 82 | } 83 | 84 | static boolean isExposableWebEndpoint(ExposableWebEndpoint webEndpoint) { 85 | return webEndpoint instanceof DiscoveredEndpoint; 86 | } 87 | 88 | static boolean isReadWebOperationCandidate(WebOperation webOperation) { 89 | if (webOperation instanceof AbstractDiscoveredOperation) { 90 | AbstractDiscoveredOperation discoveredOperation = (AbstractDiscoveredOperation) webOperation; 91 | OperationMethod operationMethod = discoveredOperation.getOperationMethod(); 92 | if (READ.equals(operationMethod.getOperationType())) { 93 | Method method = operationMethod.getMethod(); 94 | if (method.getParameterCount() == 0) { 95 | return true; 96 | } 97 | } 98 | } 99 | return false; 100 | } 101 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/properties/metadata/ConfigurationMetadataReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package io.microsphere.spring.boot.context.properties.metadata; 18 | 19 | import io.microsphere.logging.Logger; 20 | import org.springframework.boot.configurationprocessor.metadata.ConfigurationMetadata; 21 | import org.springframework.boot.configurationprocessor.metadata.JsonMarshaller; 22 | import org.springframework.context.ResourceLoaderAware; 23 | import org.springframework.core.io.Resource; 24 | import org.springframework.core.io.ResourceLoader; 25 | import org.springframework.core.io.support.PathMatchingResourcePatternResolver; 26 | import org.springframework.core.io.support.ResourcePatternResolver; 27 | 28 | import java.io.InputStream; 29 | 30 | import static io.microsphere.logging.LoggerFactory.getLogger; 31 | import static org.springframework.core.io.support.ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX; 32 | 33 | /** 34 | * {@link ConfigurationMetadata} Reader 35 | *

Example Usage

36 | *
{@code
37 |  * ConfigurationMetadataReader reader = new ConfigurationMetadataReader();
38 |  * reader.setResourceLoader(resourceLoader); // Optional, will use default if not set
39 |  * ConfigurationMetadata metadata = reader.read();
40 |  * }
41 | * 42 | * @author
Mercy 43 | * @since 1.0.0 44 | */ 45 | public class ConfigurationMetadataReader implements ResourceLoaderAware { 46 | 47 | private final static Logger logger = getLogger(ConfigurationMetadataReader.class); 48 | 49 | public static final String METADATA_PATH = CLASSPATH_ALL_URL_PREFIX + "/META-INF/spring-configuration-metadata.json"; 50 | 51 | public static final String ADDITIONAL_METADATA_PATH = CLASSPATH_ALL_URL_PREFIX + "/META-INF/additional-spring-configuration-metadata.json"; 52 | 53 | private ResourcePatternResolver resourcePatternResolver; 54 | 55 | public ConfigurationMetadata read() { 56 | ConfigurationMetadata metadata = new ConfigurationMetadata(); 57 | readMetadata(metadata, METADATA_PATH); 58 | readMetadata(metadata, ADDITIONAL_METADATA_PATH); 59 | return metadata; 60 | } 61 | 62 | private void readMetadata(ConfigurationMetadata metadata, String locationPattern) { 63 | ResourcePatternResolver resourcePatternResolver = getResourcePatternResolver(); 64 | try { 65 | Resource[] resources = resourcePatternResolver.getResources(locationPattern); 66 | for (Resource resource : resources) { 67 | readMetadata(metadata, resource); 68 | } 69 | } catch (Exception e) { 70 | logger.error("The configuration metadata resource pattern['{}'] can't be read", locationPattern, e); 71 | } 72 | } 73 | 74 | private void readMetadata(ConfigurationMetadata metadata, Resource resource) throws Exception { 75 | JsonMarshaller jsonMarshaller = new JsonMarshaller(); 76 | try (InputStream inputStream = resource.getInputStream()) { 77 | ConfigurationMetadata resourceMetadata = jsonMarshaller.read(inputStream); 78 | metadata.merge(resourceMetadata); 79 | } 80 | } 81 | 82 | @Override 83 | public void setResourceLoader(ResourceLoader resourceLoader) { 84 | if (resourceLoader instanceof ResourcePatternResolver) { 85 | this.resourcePatternResolver = (ResourcePatternResolver) resourceLoader; 86 | } else { 87 | this.resourcePatternResolver = new PathMatchingResourcePatternResolver(resourceLoader); 88 | } 89 | } 90 | 91 | public ResourcePatternResolver getResourcePatternResolver() { 92 | ResourcePatternResolver resourcePatternResolver = this.resourcePatternResolver; 93 | if (resourcePatternResolver == null) { 94 | resourcePatternResolver = new PathMatchingResourcePatternResolver(); 95 | } 96 | return resourcePatternResolver; 97 | } 98 | } -------------------------------------------------------------------------------- /microsphere-spring-boot-core/src/main/java/io/microsphere/spring/boot/context/OnceApplicationPreparedEventListener.java: -------------------------------------------------------------------------------- 1 | package io.microsphere.spring.boot.context; 2 | 3 | import io.microsphere.logging.Logger; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.context.event.ApplicationPreparedEvent; 6 | import org.springframework.context.ApplicationListener; 7 | import org.springframework.context.ConfigurableApplicationContext; 8 | import org.springframework.core.Ordered; 9 | 10 | import java.util.Map; 11 | import java.util.Set; 12 | import java.util.concurrent.ConcurrentHashMap; 13 | import java.util.concurrent.ConcurrentSkipListSet; 14 | 15 | import static io.microsphere.logging.LoggerFactory.getLogger; 16 | 17 | /** 18 | * This abstract class provides a base implementation for application listeners that should only 19 | * execute once per application context. It handles the logic of tracking which contexts have 20 | * already been processed to prevent duplicate execution. 21 | * 22 | *

Example Usage

23 | *
{@code
 24 |  * public class MyOnceApplicationPreparedEventListener extends OnceApplicationPreparedEventListener {
 25 |  *
 26 |  *     @Override
 27 |  *     protected boolean isIgnored(SpringApplication springApplication, String[] args,
 28 |  *                               ConfigurableApplicationContext context) {
 29 |  *         // Return true to skip processing for this context
 30 |  *         return false; // Process all contexts by default
 31 |  *     }
 32 |  *
 33 |  *     @Override
 34 |  *     protected void onApplicationEvent(SpringApplication springApplication, String[] args,
 35 |  *                                     ConfigurableApplicationContext context) {
 36 |  *         // Your one-time initialization logic here
 37 |  *         System.out.println("Application prepared event handled once for context: " + context.getId());
 38 |  *     }
 39 |  * }
 40 |  * }
41 | * 42 | * @author Mercy 43 | * @see io.microsphere.spring.context.event.OnceApplicationContextEventListener 44 | * @since 1.0.0 45 | **/ 46 | public abstract class OnceApplicationPreparedEventListener implements ApplicationListener, Ordered { 47 | 48 | private static Map, Set> listenerProcessedContextIds = new ConcurrentHashMap<>(); 49 | 50 | protected final Logger logger = getLogger(getClass()); 51 | 52 | private final Set processedContextIds; 53 | 54 | private int order = LOWEST_PRECEDENCE; 55 | 56 | public OnceApplicationPreparedEventListener() { 57 | this.processedContextIds = getProcessedContextIds(getClass()); 58 | } 59 | 60 | @Override 61 | public final void onApplicationEvent(ApplicationPreparedEvent event) { 62 | 63 | ConfigurableApplicationContext context = event.getApplicationContext(); 64 | 65 | String contextId = context.getId(); 66 | 67 | if (isProcessed(contextId)) { 68 | logger.trace("Current ApplicationContext[id : {}] has been processed!", contextId); 69 | return; 70 | } 71 | 72 | SpringApplication springApplication = event.getSpringApplication(); 73 | String[] args = event.getArgs(); 74 | 75 | if (isIgnored(springApplication, args, context)) { 76 | markProcessed(contextId); 77 | logger.trace("Current ApplicationContext[id : {}] is ignored!", contextId); 78 | return; 79 | } 80 | 81 | markProcessed(contextId); 82 | 83 | onApplicationEvent(springApplication, args, context); 84 | 85 | } 86 | 87 | protected boolean isProcessed(String contextId) { 88 | return processedContextIds.contains(contextId); 89 | } 90 | 91 | protected void markProcessed(String contextId) { 92 | processedContextIds.add(contextId); 93 | logger.trace("Current ApplicationContext[id : {}] was mark to be 'processed'", contextId); 94 | } 95 | 96 | protected abstract boolean isIgnored(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context); 97 | 98 | protected abstract void onApplicationEvent(SpringApplication springApplication, String[] args, ConfigurableApplicationContext context); 99 | 100 | public final void setOrder(int order) { 101 | this.order = order; 102 | } 103 | 104 | @Override 105 | public final int getOrder() { 106 | return order; 107 | } 108 | 109 | private static Set getProcessedContextIds(Class listenerClass) { 110 | return listenerProcessedContextIds.computeIfAbsent(listenerClass, type -> new ConcurrentSkipListSet<>()); 111 | } 112 | } --------------------------------------------------------------------------------