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 extends ApplicationListener> listenerClass) {
110 | return listenerProcessedContextIds.computeIfAbsent(listenerClass, type -> new ConcurrentSkipListSet<>());
111 | }
112 | }
--------------------------------------------------------------------------------