Browse Source

Merge branch '3.4.x'

Closes gh-45803
pull/45855/head
Andy Wilkinson 8 months ago
parent
commit
086646100f
  1. 22
      spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnAvailableEndpointCondition.java
  2. 7
      spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpointTests.java
  3. 72
      spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/WithTestEndpointOutcomeExposureContributor.java

22
spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/OnAvailableEndpointCondition.java

@ -71,12 +71,11 @@ class OnAvailableEndpointCondition extends SpringBootCondition { @@ -71,12 +71,11 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
Environment environment = context.getEnvironment();
MergedAnnotation<ConditionalOnAvailableEndpoint> conditionAnnotation = metadata.getAnnotations()
.get(ConditionalOnAvailableEndpoint.class);
Class<?> target = getTarget(context, metadata, conditionAnnotation);
MergedAnnotation<Endpoint> endpointAnnotation = getEndpointAnnotation(target);
return getMatchOutcome(environment, conditionAnnotation, endpointAnnotation);
return getMatchOutcome(context, conditionAnnotation, endpointAnnotation);
}
private Class<?> getTarget(ConditionContext context, AnnotatedTypeMetadata metadata,
@ -109,16 +108,17 @@ class OnAvailableEndpointCondition extends SpringBootCondition { @@ -109,16 +108,17 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
return getEndpointAnnotation(extension.getClass("endpoint"));
}
private ConditionOutcome getMatchOutcome(Environment environment,
private ConditionOutcome getMatchOutcome(ConditionContext context,
MergedAnnotation<ConditionalOnAvailableEndpoint> conditionAnnotation,
MergedAnnotation<Endpoint> endpointAnnotation) {
ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnAvailableEndpoint.class);
Environment environment = context.getEnvironment();
EndpointId endpointId = EndpointId.of(environment, endpointAnnotation.getString("id"));
ConditionOutcome accessOutcome = getAccessOutcome(environment, endpointAnnotation, endpointId, message);
if (!accessOutcome.isMatch()) {
return accessOutcome;
}
ConditionOutcome exposureOutcome = getExposureOutcome(environment, conditionAnnotation, endpointAnnotation,
ConditionOutcome exposureOutcome = getExposureOutcome(context, conditionAnnotation, endpointAnnotation,
endpointId, message);
return (exposureOutcome != null) ? exposureOutcome : ConditionOutcome.noMatch(message.because("not exposed"));
}
@ -137,11 +137,11 @@ class OnAvailableEndpointCondition extends SpringBootCondition { @@ -137,11 +137,11 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
.accessFor(endpointId, defaultAccess);
}
private ConditionOutcome getExposureOutcome(Environment environment,
private ConditionOutcome getExposureOutcome(ConditionContext context,
MergedAnnotation<ConditionalOnAvailableEndpoint> conditionAnnotation,
MergedAnnotation<Endpoint> endpointAnnotation, EndpointId endpointId, Builder message) {
Set<EndpointExposure> exposures = getExposures(conditionAnnotation);
Set<EndpointExposureOutcomeContributor> outcomeContributors = getExposureOutcomeContributors(environment);
Set<EndpointExposureOutcomeContributor> outcomeContributors = getExposureOutcomeContributors(context);
for (EndpointExposureOutcomeContributor outcomeContributor : outcomeContributors) {
ConditionOutcome outcome = outcomeContributor.getExposureOutcome(endpointId, exposures, message);
if (outcome != null && outcome.isMatch()) {
@ -166,7 +166,8 @@ class OnAvailableEndpointCondition extends SpringBootCondition { @@ -166,7 +166,8 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
return result;
}
private Set<EndpointExposureOutcomeContributor> getExposureOutcomeContributors(Environment environment) {
private Set<EndpointExposureOutcomeContributor> getExposureOutcomeContributors(ConditionContext context) {
Environment environment = context.getEnvironment();
Set<EndpointExposureOutcomeContributor> contributors = exposureOutcomeContributorsCache.get(environment);
if (contributors == null) {
contributors = new LinkedHashSet<>();
@ -174,15 +175,16 @@ class OnAvailableEndpointCondition extends SpringBootCondition { @@ -174,15 +175,16 @@ class OnAvailableEndpointCondition extends SpringBootCondition {
if (environment.getProperty(JMX_ENABLED_KEY, Boolean.class, false)) {
contributors.add(new StandardExposureOutcomeContributor(environment, EndpointExposure.JMX));
}
contributors.addAll(loadExposureOutcomeContributors(environment));
contributors.addAll(loadExposureOutcomeContributors(context.getClassLoader(), environment));
exposureOutcomeContributorsCache.put(environment, contributors);
}
return contributors;
}
private List<EndpointExposureOutcomeContributor> loadExposureOutcomeContributors(Environment environment) {
private List<EndpointExposureOutcomeContributor> loadExposureOutcomeContributors(ClassLoader classLoader,
Environment environment) {
ArgumentResolver argumentResolver = ArgumentResolver.of(Environment.class, environment);
return SpringFactoriesLoader.forDefaultResourceLocation()
return SpringFactoriesLoader.forDefaultResourceLocation(classLoader)
.load(EndpointExposureOutcomeContributor.class, argumentResolver);
}

7
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/ConditionalOnAvailableEndpointTests.java

@ -294,6 +294,13 @@ class ConditionalOnAvailableEndpointTests { @@ -294,6 +294,13 @@ class ConditionalOnAvailableEndpointTests {
.run((context) -> assertThat(context).hasSingleBean(DisabledButAccessibleEndpoint.class));
}
@Test
@WithTestEndpointOutcomeExposureContributor
void exposureOutcomeContributorCanMakeEndpointAvailable() {
this.contextRunner.withPropertyValues("management.endpoints.test.exposure.include=test")
.run((context) -> assertThat(context).hasSingleBean(TestEndpoint.class));
}
@Endpoint(id = "health")
static class HealthEndpoint {

72
spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/endpoint/condition/WithTestEndpointOutcomeExposureContributor.java

@ -0,0 +1,72 @@ @@ -0,0 +1,72 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.actuate.autoconfigure.endpoint.condition;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.Set;
import org.springframework.boot.actuate.autoconfigure.endpoint.expose.EndpointExposure;
import org.springframework.boot.actuate.autoconfigure.endpoint.expose.IncludeExcludeEndpointFilter;
import org.springframework.boot.actuate.endpoint.EndpointId;
import org.springframework.boot.actuate.endpoint.ExposableEndpoint;
import org.springframework.boot.autoconfigure.condition.ConditionMessage.Builder;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.core.env.Environment;
import org.springframework.core.io.support.SpringFactoriesLoader;
/**
* Makes a test {@link EndpointExposureOutcomeContributor} available via
* {@link SpringFactoriesLoader}.
*
* @author Andy Wilkinson
*/
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@WithResource(name = "META-INF/spring.factories",
content = """
org.springframework.boot.actuate.autoconfigure.endpoint.condition.EndpointExposureOutcomeContributor=\
org.springframework.boot.actuate.autoconfigure.endpoint.condition.WithTestEndpointOutcomeExposureContributor.TestEndpointExposureOutcomeContributor
""")
public @interface WithTestEndpointOutcomeExposureContributor {
class TestEndpointExposureOutcomeContributor implements EndpointExposureOutcomeContributor {
private final IncludeExcludeEndpointFilter<?> filter;
TestEndpointExposureOutcomeContributor(Environment environment) {
this.filter = new IncludeExcludeEndpointFilter<>(ExposableEndpoint.class, environment,
"management.endpoints.test.exposure");
}
@Override
public ConditionOutcome getExposureOutcome(EndpointId endpointId, Set<EndpointExposure> exposures,
Builder message) {
if (this.filter.match(endpointId)) {
return ConditionOutcome.match();
}
return null;
}
}
}
Loading…
Cancel
Save