mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Reinstate support for relaxed binding for endpoint enablement
This commit improves upon the changes made in a8bf9d3
by adding
support for relaxed binding of the endpoints.enabled and
endpoints.<name>.enabled properties. This is achieved by replacing
use of @ConditionalOnExpression (which does not support relaxed
binding) with a custom condition implementation that uses
RelaxedPropertyResolver.
Closes gh-2767
This commit is contained in:
parent
d8f45ab6ca
commit
83f842a226
@ -17,6 +17,10 @@
|
||||
package org.springframework.boot.actuate.autoconfigure;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
@ -49,15 +53,17 @@ import org.springframework.boot.actuate.endpoint.mvc.ShutdownMvcEndpoint;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
|
||||
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
@ -66,10 +72,14 @@ import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ConditionContext;
|
||||
import org.springframework.context.annotation.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.event.ContextClosedEvent;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.type.AnnotatedTypeMetadata;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import org.springframework.web.servlet.DispatcherServlet;
|
||||
@ -156,14 +166,14 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(EnvironmentEndpoint.class)
|
||||
@ConditionalOnExpression("${endpoints.env.enabled:${endpoints.enabled:true}}")
|
||||
@ConditionalOnEnabledEndpoint("env")
|
||||
public EnvironmentMvcEndpoint environmentMvcEndpoint(EnvironmentEndpoint delegate) {
|
||||
return new EnvironmentMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(HealthEndpoint.class)
|
||||
@ConditionalOnExpression("${endpoints.health.enabled:${endpoints.enabled:true}}")
|
||||
@ConditionalOnEnabledEndpoint("health")
|
||||
public HealthMvcEndpoint healthMvcEndpoint(HealthEndpoint delegate) {
|
||||
Security security = this.managementServerProperties.getSecurity();
|
||||
boolean secure = (security == null || security.isEnabled());
|
||||
@ -177,14 +187,14 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(MetricsEndpoint.class)
|
||||
@ConditionalOnExpression("${endpoints.metrics.enabled:${endpoints.enabled:true}}")
|
||||
@ConditionalOnEnabledEndpoint("metrics")
|
||||
public MetricsMvcEndpoint metricsMvcEndpoint(MetricsEndpoint delegate) {
|
||||
return new MetricsMvcEndpoint(delegate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnBean(ShutdownEndpoint.class)
|
||||
@ConditionalOnExpression("${endpoints.shutdown.enabled:false}")
|
||||
@ConditionalOnEnabledEndpoint(value = "shutdown", enabledByDefault = false)
|
||||
public ShutdownMvcEndpoint shutdownMvcEndpoint(ShutdownEndpoint delegate) {
|
||||
return new ShutdownMvcEndpoint(delegate);
|
||||
}
|
||||
@ -330,4 +340,77 @@ public class EndpointWebMvcAutoConfiguration implements ApplicationContextAware,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link Conditional} that checks whether or not an endpoint is enabled. Matches if
|
||||
* the value of the {@code endpoints.<name>.enabled} property is {@code true}. Does
|
||||
* not match if the property's value or {@code enabledByDefault} is {@code false}.
|
||||
* Otherwise, matches if the value of the {@code endpoints.enabled} property is
|
||||
* {@code true} or if the property is not configured.
|
||||
*
|
||||
* @since 1.2.4
|
||||
*/
|
||||
@Conditional(OnEnabledEndpointCondition.class)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
public static @interface ConditionalOnEnabledEndpoint {
|
||||
|
||||
/**
|
||||
* The name of the endpoint.
|
||||
* @return The name of the endpoint
|
||||
*/
|
||||
public String value();
|
||||
|
||||
/**
|
||||
* Returns whether or not the endpoint is enabled by default.
|
||||
* @return {@code true} if the endpoint is enabled by default, otherwise
|
||||
* {@code false}
|
||||
*/
|
||||
public boolean enabledByDefault() default true;
|
||||
|
||||
}
|
||||
|
||||
private static class OnEnabledEndpointCondition extends SpringBootCondition {
|
||||
|
||||
@Override
|
||||
public ConditionOutcome getMatchOutcome(ConditionContext context,
|
||||
AnnotatedTypeMetadata metadata) {
|
||||
AnnotationAttributes annotationAttributes = AnnotationAttributes
|
||||
.fromMap(metadata.getAnnotationAttributes(ConditionalOnEnabledEndpoint.class
|
||||
.getName()));
|
||||
String endpointName = annotationAttributes.getString("value");
|
||||
boolean enabledByDefault = annotationAttributes
|
||||
.getBoolean("enabledByDefault");
|
||||
ConditionOutcome specificEndpointOutcome = determineSpecificEndpointOutcome(
|
||||
endpointName, enabledByDefault, context);
|
||||
if (specificEndpointOutcome != null) {
|
||||
return specificEndpointOutcome;
|
||||
}
|
||||
return determineAllEndpointsOutcome(context);
|
||||
|
||||
}
|
||||
|
||||
private ConditionOutcome determineSpecificEndpointOutcome(String endpointName,
|
||||
boolean enabledByDefault, ConditionContext context) {
|
||||
RelaxedPropertyResolver endpointPropertyResolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "endpoints." + endpointName + ".");
|
||||
if (endpointPropertyResolver.containsProperty("enabled") || !enabledByDefault) {
|
||||
boolean match = endpointPropertyResolver.getProperty("enabled",
|
||||
Boolean.class, enabledByDefault);
|
||||
return new ConditionOutcome(match, "The " + endpointName + " is "
|
||||
+ (match ? "enabled" : "disabled"));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ConditionOutcome determineAllEndpointsOutcome(ConditionContext context) {
|
||||
RelaxedPropertyResolver allEndpointsPropertyResolver = new RelaxedPropertyResolver(
|
||||
context.getEnvironment(), "endpoints.");
|
||||
boolean match = Boolean.valueOf(allEndpointsPropertyResolver.getProperty(
|
||||
"enabled", "true"));
|
||||
return new ConditionOutcome(match, "All endpoints are "
|
||||
+ (match ? "enabled" : "disabled") + " by default");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
this.applicationContext.register(RootConfig.class, BaseConfiguration.class,
|
||||
ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class);
|
||||
EnvironmentTestUtils.addEnvironment(this.applicationContext,
|
||||
"endpoints.enabled:false");
|
||||
"ENDPOINTS_ENABLED:false");
|
||||
this.applicationContext.refresh();
|
||||
assertThat(this.applicationContext.getBeansOfType(MvcEndpoint.class).size(),
|
||||
is(equalTo(0)));
|
||||
@ -342,7 +342,7 @@ public class EndpointWebMvcAutoConfigurationTests {
|
||||
ServerPortConfig.class, EndpointWebMvcAutoConfiguration.class);
|
||||
EnvironmentTestUtils.addEnvironment(this.applicationContext,
|
||||
"endpoints.enabled:false",
|
||||
String.format("endpoints.%s.enabled:true", name));
|
||||
String.format("endpoints_%s_enabled:true", name));
|
||||
this.applicationContext.refresh();
|
||||
assertThat(this.applicationContext.getBeansOfType(type).size(), is(equalTo(1)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user