Avoid actuator beans being ineligible for post-processing

Closes gh-33110
pull/33115/head
Andy Wilkinson 2 years ago
parent b5e502d03b
commit fe72f307f4

@ -21,10 +21,12 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnAvailableEndpoint;
@ -67,6 +69,7 @@ import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.util.StringUtils;
import org.springframework.util.function.SingletonSupplier;
import org.springframework.web.reactive.DispatcherHandler;
/**
@ -134,8 +137,9 @@ public class WebFluxEndpointManagementContextConfiguration {
@ConditionalOnBean(EndpointObjectMapper.class)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
static ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor serverCodecConfigurerEndpointObjectMapperBeanPostProcessor(
EndpointObjectMapper endpointObjectMapper) {
return new ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(endpointObjectMapper);
ObjectProvider<EndpointObjectMapper> endpointObjectMapper) {
return new ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(
SingletonSupplier.of(endpointObjectMapper::getObject));
}
/**
@ -147,9 +151,10 @@ public class WebFluxEndpointManagementContextConfiguration {
private static final List<MediaType> MEDIA_TYPES = Collections
.unmodifiableList(Arrays.asList(MediaType.APPLICATION_JSON, new MediaType("application", "*+json")));
private final EndpointObjectMapper endpointObjectMapper;
private final Supplier<EndpointObjectMapper> endpointObjectMapper;
ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(EndpointObjectMapper endpointObjectMapper) {
ServerCodecConfigurerEndpointObjectMapperBeanPostProcessor(
Supplier<EndpointObjectMapper> endpointObjectMapper) {
this.endpointObjectMapper = endpointObjectMapper;
}
@ -173,7 +178,7 @@ public class WebFluxEndpointManagementContextConfiguration {
if (encoder instanceof Jackson2JsonEncoder) {
Jackson2JsonEncoder jackson2JsonEncoder = (Jackson2JsonEncoder) encoder;
jackson2JsonEncoder.registerObjectMappersForType(OperationResponseBody.class, (associations) -> {
ObjectMapper objectMapper = this.endpointObjectMapper.get();
ObjectMapper objectMapper = this.endpointObjectMapper.get().get();
MEDIA_TYPES.forEach((mimeType) -> associations.put(mimeType, objectMapper));
});
}

@ -44,7 +44,7 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
private final boolean hasNoCompositeMeterRegistryBeans;
private final boolean useGlobalRegistry;
private final ObjectProvider<MetricsProperties> properties;
private final ObjectProvider<MeterRegistryCustomizer<?>> customizers;
@ -56,22 +56,21 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
private final Set<MeterRegistry> deferredBindings = new LinkedHashSet<>();
MeterRegistryPostProcessor(ApplicationContext applicationContext, MetricsProperties metricsProperties,
ObjectProvider<MeterRegistryCustomizer<?>> customizers, ObjectProvider<MeterFilter> filters,
ObjectProvider<MeterBinder> binders) {
this(hasNoCompositeMeterRegistryBeans(applicationContext), metricsProperties.isUseGlobalRegistry(), customizers,
filters, binders);
MeterRegistryPostProcessor(ApplicationContext applicationContext,
ObjectProvider<MetricsProperties> metricsProperties, ObjectProvider<MeterRegistryCustomizer<?>> customizers,
ObjectProvider<MeterFilter> filters, ObjectProvider<MeterBinder> binders) {
this(hasNoCompositeMeterRegistryBeans(applicationContext), metricsProperties, customizers, filters, binders);
}
private static boolean hasNoCompositeMeterRegistryBeans(ApplicationContext applicationContext) {
return applicationContext.getBeanNamesForType(CompositeMeterRegistry.class, false, false).length == 0;
}
MeterRegistryPostProcessor(boolean hasNoCompositeMeterRegistryBeans, boolean useGlobalRegistry,
MeterRegistryPostProcessor(boolean hasNoCompositeMeterRegistryBeans, ObjectProvider<MetricsProperties> properties,
ObjectProvider<MeterRegistryCustomizer<?>> customizers, ObjectProvider<MeterFilter> filters,
ObjectProvider<MeterBinder> binders) {
this.hasNoCompositeMeterRegistryBeans = hasNoCompositeMeterRegistryBeans;
this.useGlobalRegistry = useGlobalRegistry;
this.properties = properties;
this.customizers = customizers;
this.filters = filters;
this.binders = binders;
@ -121,7 +120,7 @@ class MeterRegistryPostProcessor implements BeanPostProcessor, SmartInitializing
}
private void addToGlobalRegistryIfNecessary(MeterRegistry meterRegistry) {
if (this.useGlobalRegistry && !isGlobalRegistry(meterRegistry)) {
if (this.properties.getObject().isUseGlobalRegistry() && !isGlobalRegistry(meterRegistry)) {
Metrics.addRegistry(meterRegistry);
}
}

@ -51,7 +51,8 @@ public class MetricsAutoConfiguration {
@Bean
public static MeterRegistryPostProcessor meterRegistryPostProcessor(ApplicationContext applicationContext,
MetricsProperties metricsProperties, ObjectProvider<MeterRegistryCustomizer<?>> meterRegistryCustomizers,
ObjectProvider<MetricsProperties> metricsProperties,
ObjectProvider<MeterRegistryCustomizer<?>> meterRegistryCustomizers,
ObjectProvider<MeterFilter> meterFilters, ObjectProvider<MeterBinder> meterBinders) {
return new MeterRegistryPostProcessor(applicationContext, metricsProperties, meterRegistryCustomizers,
meterFilters, meterBinders);

@ -48,6 +48,8 @@ import static org.mockito.Mockito.mock;
@ExtendWith(MockitoExtension.class)
class MeterRegistryPostProcessorTests {
private final MetricsProperties properties = new MetricsProperties();
private List<MeterRegistryCustomizer<?>> customizers = new ArrayList<>();
private List<MeterFilter> filters = new ArrayList<>();
@ -69,12 +71,16 @@ class MeterRegistryPostProcessorTests {
@Mock
private Config mockConfig;
MeterRegistryPostProcessorTests() {
this.properties.setUseGlobalRegistry(false);
}
@Test
void postProcessAndInitializeWhenCompositeAppliesCustomizer() {
this.customizers.add(this.mockCustomizer);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
CompositeMeterRegistry composite = new CompositeMeterRegistry();
postProcessAndInitialize(processor, composite);
then(this.mockCustomizer).should().customize(composite);
@ -84,9 +90,9 @@ class MeterRegistryPostProcessorTests {
void postProcessAndInitializeAppliesCustomizer() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.customizers.add(this.mockCustomizer);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockCustomizer).should().customize(this.mockRegistry);
}
@ -95,9 +101,9 @@ class MeterRegistryPostProcessorTests {
void postProcessAndInitializeAppliesFilter() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.filters.add(this.mockFilter);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockConfig).should().meterFilter(this.mockFilter);
}
@ -106,9 +112,9 @@ class MeterRegistryPostProcessorTests {
void postProcessAndInitializeBindsTo() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockBinder).should().bindTo(this.mockRegistry);
}
@ -116,9 +122,9 @@ class MeterRegistryPostProcessorTests {
@Test
void postProcessAndInitializeWhenCompositeBindsTo() {
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
CompositeMeterRegistry composite = new CompositeMeterRegistry();
postProcessAndInitialize(processor, composite);
then(this.mockBinder).should().bindTo(composite);
@ -127,8 +133,9 @@ class MeterRegistryPostProcessorTests {
@Test
void postProcessAndInitializeWhenCompositeExistsDoesNotBindTo() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters), null);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(false,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), null);
postProcessAndInitialize(processor, this.mockRegistry);
then(this.mockBinder).shouldHaveNoInteractions();
}
@ -139,9 +146,9 @@ class MeterRegistryPostProcessorTests {
this.customizers.add(this.mockCustomizer);
this.filters.add(this.mockFilter);
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
InOrder ordered = inOrder(this.mockBinder, this.mockConfig, this.mockCustomizer);
then(this.mockCustomizer).should(ordered).customize(this.mockRegistry);
@ -152,9 +159,10 @@ class MeterRegistryPostProcessorTests {
@Test
void postProcessAndInitializeWhenUseGlobalRegistryTrueAddsToGlobalRegistry() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, true,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
this.properties.setUseGlobalRegistry(true);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
try {
postProcessAndInitialize(processor, this.mockRegistry);
assertThat(Metrics.globalRegistry.getRegistries()).contains(this.mockRegistry);
@ -167,9 +175,9 @@ class MeterRegistryPostProcessorTests {
@Test
void postProcessAndInitializeWhenUseGlobalRegistryFalseDoesNotAddToGlobalRegistry() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
postProcessAndInitialize(processor, this.mockRegistry);
assertThat(Metrics.globalRegistry.getRegistries()).doesNotContain(this.mockRegistry);
}
@ -178,9 +186,9 @@ class MeterRegistryPostProcessorTests {
void postProcessDoesNotBindToUntilSingletonsInitialized() {
given(this.mockRegistry.config()).willReturn(this.mockConfig);
this.binders.add(this.mockBinder);
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true, false,
createObjectProvider(this.customizers), createObjectProvider(this.filters),
createObjectProvider(this.binders));
MeterRegistryPostProcessor processor = new MeterRegistryPostProcessor(true,
createObjectProvider(this.properties), createObjectProvider(this.customizers),
createObjectProvider(this.filters), createObjectProvider(this.binders));
processor.postProcessAfterInitialization(this.mockRegistry, "meterRegistry");
then(this.mockBinder).shouldHaveNoInteractions();
processor.afterSingletonsInstantiated();
@ -199,4 +207,11 @@ class MeterRegistryPostProcessorTests {
return objectProvider;
}
@SuppressWarnings("unchecked")
private <T> ObjectProvider<T> createObjectProvider(T object) {
ObjectProvider<T> objectProvider = mock(ObjectProvider.class);
given(objectProvider.getObject()).willReturn(object);
return objectProvider;
}
}

Loading…
Cancel
Save