Skip to content

Commit 0221e3d

Browse files
committed
Switch HasFeatures bean names and add conditional
Rename HasFeatures beans to use a ".features" suffix instead of the "HasFeatures." prefix and centralize feature availability condition. Introduces a NAME constant and BEAN_NAME_SUFFIX, updates PROPERTY_PREFIX and related property name patterns, and updates getBeanName usage accordingly. Adds a new @ConditionalOnFeaturesAvailable annotation (combining features-enabled and FeaturesEndpoint availability) and removes the previous direct ConditionalOnAvailableEndpoint usage. Tests were updated to assert the new constants and behavior. Also bumps microsphere-spring-boot version in the parent POM and updates README module versions.
1 parent fb0c28d commit 0221e3d

5 files changed

Lines changed: 105 additions & 14 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ Then declare only the modules you need (versions are managed by the BOM):
114114

115115
| **Branch** | **Spring Cloud compatibility** | **Latest version** |
116116
|------------|----------------------------------------|--------------------|
117-
| `main` | 2022.0.x, 2023.0.x, 2024.0.x, 2025.0.x | `0.2.16` |
118-
| `1.x` | Hoxton, 2020.0.x, 2021.0.x | `0.1.16` |
117+
| `main` | 2022.0.x, 2023.0.x, 2024.0.x, 2025.0.x | `0.2.17` |
118+
| `1.x` | Hoxton, 2020.0.x, 2021.0.x | `0.1.17` |
119119

120120
By default, the `main` branch builds against Spring Cloud 2025.0.x. To build or run tests against an older generation,
121121
activate the corresponding Maven profile:

microsphere-spring-cloud-commons/src/main/java/io/microsphere/spring/cloud/client/actuator/ConfigurationPropertyHasFeaturesAutoConfiguration.java

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,14 @@
1818
package io.microsphere.spring.cloud.client.actuator;
1919

2020
import io.microsphere.logging.Logger;
21-
import io.microsphere.spring.cloud.client.condition.ConditionalOnFeaturesEnabled;
21+
import io.microsphere.spring.cloud.client.condition.ConditionalOnFeaturesAvailable;
2222
import io.microsphere.spring.context.config.AutoRegistrationBean;
2323
import org.springframework.beans.BeansException;
2424
import org.springframework.beans.factory.BeanClassLoaderAware;
2525
import org.springframework.beans.factory.BeanFactory;
2626
import org.springframework.beans.factory.BeanFactoryAware;
2727
import org.springframework.beans.factory.config.SingletonBeanRegistry;
28-
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
2928
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
30-
import org.springframework.cloud.client.actuator.FeaturesEndpoint;
3129
import org.springframework.cloud.client.actuator.HasFeatures;
3230
import org.springframework.cloud.client.actuator.NamedFeature;
3331
import org.springframework.context.EnvironmentAware;
@@ -79,26 +77,27 @@
7977
*
8078
* <h3>Resulting Beans</h3>
8179
* For each module found in the configuration, a {@link HasFeatures} bean is registered with the name format:
82-
* {@code HasFeatures.{module-name}} (e.g., {@code HasFeatures.jdbc}, {@code HasFeatures.web}).
80+
* {@code HasFeatures.{module-name}} (e.g., {@code jdbc.features}, {@code web.features}).
8381
*
8482
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
8583
* @see HasFeatures
8684
* @see NamedFeature
8785
* @see AutoRegistrationBean
8886
* @since 1.0.0
8987
*/
90-
@ConditionalOnFeaturesEnabled
91-
@ConditionalOnAvailableEndpoint(endpoint = FeaturesEndpoint.class)
88+
@ConditionalOnFeaturesAvailable
9289
@AutoConfigureBefore(name = "org.springframework.cloud.client.CommonsClientAutoConfiguration")
9390
public class ConfigurationPropertyHasFeaturesAutoConfiguration implements BeanFactoryAware, BeanClassLoaderAware,
9491
EnvironmentAware {
9592

9693
private static final Logger logger = getLogger(ConfigurationPropertyHasFeaturesAutoConfiguration.class);
9794

95+
static final String NAME = "features";
96+
9897
/**
9998
* The prefix of the configuration properties for {@link HasFeatures} : "microsphere.spring.cloud.features."
10099
*/
101-
public static final String PROPERTY_PREFIX = MICROSPHERE_SPRING_CLOUD_PROPERTY_NAME_PREFIX + "features.";
100+
public static final String PROPERTY_PREFIX = MICROSPHERE_SPRING_CLOUD_PROPERTY_NAME_PREFIX + NAME + DOT;
102101

103102
/**
104103
* The pattern of the configuration properties for abstract features: "microsphere.spring.cloud.features.{module-name}"
@@ -111,9 +110,9 @@ public class ConfigurationPropertyHasFeaturesAutoConfiguration implements BeanFa
111110
public static final String NAMED_FEATURE_PROPERTY_NAME_PATTERN = ABSTRACT_FEATURE_PROPERTY_NAME_PATTERN + DOT + "{}";
112111

113112
/**
114-
* The prefix of the bean name for {@link HasFeatures} : "HasFeatures."
113+
* The suffix of the bean name for {@link HasFeatures} : ".features"
115114
*/
116-
public static final String BEAN_NAME_PREFIX = "HasFeatures.";
115+
public static final String BEAN_NAME_SUFFIX = DOT + NAME;
117116

118117
private ClassLoader classLoader;
119118

@@ -193,14 +192,14 @@ public static String getNamedFeaturePropertyName(String moduleName, String featu
193192
* <pre>{@code
194193
* // For module name "jdbc"
195194
* String beanName = getBeanName("jdbc");
196-
* // Result: "HasFeatures.jdbc"
195+
* // Result: "jdbc.features"
197196
* }</pre>
198197
*
199198
* @param moduleName the name of the module
200199
* @return the bean name for {@link HasFeatures}
201200
*/
202201
public static String getBeanName(String moduleName) {
203-
return BEAN_NAME_PREFIX + moduleName;
202+
return moduleName + BEAN_NAME_SUFFIX;
204203
}
205204

206205
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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.cloud.client.condition;
18+
19+
import io.microsphere.spring.cloud.commons.constants.CommonsPropertyConstants;
20+
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
21+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
22+
import org.springframework.cloud.client.CommonsClientAutoConfiguration;
23+
import org.springframework.cloud.client.actuator.FeaturesEndpoint;
24+
import org.springframework.cloud.client.actuator.HasFeatures;
25+
26+
import java.lang.annotation.Documented;
27+
import java.lang.annotation.Retention;
28+
import java.lang.annotation.Target;
29+
30+
import static io.microsphere.spring.cloud.commons.constants.CommonsPropertyConstants.FEATURES_ENABLED_PROPERTY_NAME;
31+
import static java.lang.annotation.ElementType.METHOD;
32+
import static java.lang.annotation.ElementType.TYPE;
33+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
34+
35+
/**
36+
* {@link org.springframework.context.annotation.Conditional} that only matches when Spring Cloud features are enabled
37+
* and the {@link FeaturesEndpoint} is available.
38+
* <p>
39+
* This annotation combines {@link ConditionalOnFeaturesEnabled} and {@link ConditionalOnAvailableEndpoint} to ensure
40+
* that the annotated component is only created if the application has explicitly enabled Spring Cloud features
41+
* (via the property defined in {@link CommonsPropertyConstants#FEATURES_ENABLED_PROPERTY_NAME}) and the
42+
* {@link FeaturesEndpoint} actuator endpoint is exposed and accessible.
43+
*
44+
* <h3>Example Usage</h3>
45+
* <pre>{@code
46+
* @Configuration
47+
* @ConditionalOnFeaturesAvailable
48+
* public class MyFeatureConfiguration {
49+
*
50+
* @Bean
51+
* public MyService myService() {
52+
* return new MyService();
53+
* }
54+
* }
55+
* }</pre>
56+
*
57+
* <p>
58+
* In the example above, {@code MyFeatureConfiguration} will only be loaded if:
59+
* <ul>
60+
* <li>The property {@code microsphere.spring.cloud.features.enabled} is set to {@code true}.</li>
61+
* <li>The {@link FeaturesEndpoint} is available (i.e., included in the management endpoints).</li>
62+
* </ul>
63+
*
64+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
65+
* @see ConditionalOnFeaturesEnabled
66+
* @see ConditionalOnAvailableEndpoint
67+
* @see FeaturesEndpoint
68+
* @since 1.0.0
69+
*/
70+
@Retention(RUNTIME)
71+
@Target({TYPE, METHOD})
72+
@Documented
73+
@ConditionalOnFeaturesEnabled
74+
@ConditionalOnAvailableEndpoint(endpoint = FeaturesEndpoint.class)
75+
public @interface ConditionalOnFeaturesAvailable {
76+
}

microsphere-spring-cloud-commons/src/test/java/io/microsphere/spring/cloud/client/actuator/ConfigurationPropertyHasFeaturesAutoConfigurationTest.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
import java.util.List;
3131
import java.util.Map;
3232

33+
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.ABSTRACT_FEATURE_PROPERTY_NAME_PATTERN;
34+
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.BEAN_NAME_SUFFIX;
35+
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.NAME;
36+
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.NAMED_FEATURE_PROPERTY_NAME_PATTERN;
37+
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.PROPERTY_PREFIX;
3338
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.getBeanName;
3439
import static io.microsphere.spring.cloud.client.actuator.ConfigurationPropertyHasFeaturesAutoConfiguration.getQualifierFeatureName;
3540
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -63,6 +68,9 @@ class ConfigurationPropertyHasFeaturesAutoConfigurationTest {
6368

6469
@Test
6570
void test() {
71+
72+
testConstants();
73+
6674
HasFeatures hasFeatures = this.hasFeaturesBeansMap.get(getBeanName("jdbc"));
6775
assertNotNull(hasFeatures);
6876
assertTrue(hasFeatures.getAbstractFeatures().isEmpty());
@@ -88,4 +96,12 @@ void test() {
8896

8997
}
9098

99+
private void testConstants() {
100+
assertEquals("features", NAME);
101+
assertEquals("microsphere.spring.cloud.features.", PROPERTY_PREFIX);
102+
assertEquals("microsphere.spring.cloud.features.{}", ABSTRACT_FEATURE_PROPERTY_NAME_PATTERN);
103+
assertEquals("microsphere.spring.cloud.features.{}.{}", NAMED_FEATURE_PROPERTY_NAME_PATTERN);
104+
assertEquals(".features", BEAN_NAME_SUFFIX);
105+
}
106+
91107
}

microsphere-spring-cloud-parent/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
<properties>
2222
<!-- BOM versions -->
23-
<microsphere-spring-boot.version>0.2.18</microsphere-spring-boot.version>
23+
<microsphere-spring-boot.version>0.2.19</microsphere-spring-boot.version>
2424
<testcontainers.version>2.0.5</testcontainers.version>
2525
<!-- Testing -->
2626
<junit-jupiter.version>6.1.0</junit-jupiter.version>

0 commit comments

Comments
 (0)