From 329588ad2288983fb5e3018dcd986fa2a260c3f5 Mon Sep 17 00:00:00 2001 From: Artem Bilan Date: Thu, 14 Oct 2021 14:06:36 -0400 Subject: [PATCH] GH-3643: Defer MeterRegistry bean dependency Fixes https://github.com/spring-projects/spring-integration/issues/3643 The `ImportBeanDefinitionRegistrar` register its bean definition in the early phase. It causes a problem with Spring Boot when an explicit `@EnableIntegrationManagement` is declared: the `MeterRegistry` is provided later on via auto-configuration and `MicrometerMetricsCaptor` has no knowledge about `MeterRegistry` at the `ImportBeanDefinitionRegistrar` phase. * Reworks `MicrometerMetricsCaptorRegistrar` to the `MicrometerMetricsCaptorConfiguration` and use special conditional `MicrometerMetricsCaptorImportSelector` for that `@EnableIntegrationManagement`. This way a `MicrometerMetricsCaptor` `@Bean` consults `ObjectProvider` on its creating time and returns `null` if no `MeterRegistry` beans at all. --- .../config/EnableIntegrationManagement.java | 6 +-- .../graph/IntegrationGraphServer.java | 4 +- ...MicrometerMetricsCaptorConfiguration.java} | 30 ++++++------- ...MicrometerMetricsCaptorImportSelector.java | 42 +++++++++++++++++++ 4 files changed, 59 insertions(+), 23 deletions(-) rename spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/{MicrometerMetricsCaptorRegistrar.java => MicrometerMetricsCaptorConfiguration.java} (57%) create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorImportSelector.java diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/EnableIntegrationManagement.java b/spring-integration-core/src/main/java/org/springframework/integration/config/EnableIntegrationManagement.java index 8993738511c..ed4ea3dab42 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/EnableIntegrationManagement.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/EnableIntegrationManagement.java @@ -1,5 +1,5 @@ /* - * Copyright 2014-2020 the original author or authors. + * Copyright 2014-2021 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. @@ -23,7 +23,7 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Import; -import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptorRegistrar; +import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptorImportSelector; /** * Enables default configuring of management in Spring Integration components in an existing application. @@ -39,7 +39,7 @@ @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented -@Import({ MicrometerMetricsCaptorRegistrar.class, IntegrationManagementConfiguration.class }) +@Import({ MicrometerMetricsCaptorImportSelector.class, IntegrationManagementConfiguration.class }) public @interface EnableIntegrationManagement { /** diff --git a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java index 3f3e036302a..cae3809581b 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/graph/IntegrationGraphServer.java @@ -48,7 +48,7 @@ import org.springframework.integration.router.RecipientListRouterManagement; import org.springframework.integration.support.context.NamedComponent; import org.springframework.integration.support.management.MappingMessageRouterManagement; -import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptorRegistrar; +import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptorConfiguration; import org.springframework.integration.support.utils.IntegrationUtils; import org.springframework.lang.Nullable; import org.springframework.messaging.MessageChannel; @@ -159,7 +159,7 @@ protected Map getBeansOfType(Class type) { } private synchronized Graph buildGraph() { - if (micrometerEnhancer == null && MicrometerMetricsCaptorRegistrar.METER_REGISTRY_PRESENT) { + if (micrometerEnhancer == null && MicrometerMetricsCaptorConfiguration.METER_REGISTRY_PRESENT) { micrometerEnhancer = new MicrometerNodeEnhancer(this.applicationContext); } String implementationVersion = IntegrationGraphServer.class.getPackage().getImplementationVersion(); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorRegistrar.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java similarity index 57% rename from spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorRegistrar.java rename to spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java index 8ad3609b270..7a23b2139d5 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorRegistrar.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorConfiguration.java @@ -16,12 +16,10 @@ package org.springframework.integration.support.management.micrometer; -import org.springframework.beans.factory.ListableBeanFactory; -import org.springframework.beans.factory.config.BeanDefinition; -import org.springframework.beans.factory.support.BeanDefinitionBuilder; -import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; -import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.ClassUtils; import io.micrometer.core.instrument.MeterRegistry; @@ -35,7 +33,8 @@ * * @since 5.2.9 */ -public class MicrometerMetricsCaptorRegistrar implements ImportBeanDefinitionRegistrar { +@Configuration(proxyBeanMethods = false) +public class MicrometerMetricsCaptorConfiguration { /** * A {@code boolean} flag to indicate if the @@ -45,18 +44,13 @@ public class MicrometerMetricsCaptorRegistrar implements ImportBeanDefinitionReg public static final boolean METER_REGISTRY_PRESENT = ClassUtils.isPresent("io.micrometer.core.instrument.MeterRegistry", null); - @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - ListableBeanFactory beanFactory = (ListableBeanFactory) registry; - if (METER_REGISTRY_PRESENT - && !registry.containsBeanDefinition(MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME) - && beanFactory.getBeanNamesForType(MeterRegistry.class, false, false).length > 0) { - - registry.registerBeanDefinition(MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME, - BeanDefinitionBuilder.genericBeanDefinition(MicrometerMetricsCaptor.class, - () -> new MicrometerMetricsCaptor(beanFactory.getBeanProvider(MeterRegistry.class))) - .setRole(BeanDefinition.ROLE_INFRASTRUCTURE) - .getBeanDefinition()); + @Bean(name = MicrometerMetricsCaptor.MICROMETER_CAPTOR_NAME) + public MicrometerMetricsCaptor micrometerMetricsCaptor(ObjectProvider meterRegistries) { + if (meterRegistries.stream().findAny().isPresent()) { + return new MicrometerMetricsCaptor(meterRegistries); + } + else { + return null; } } diff --git a/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorImportSelector.java b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorImportSelector.java new file mode 100644 index 00000000000..e5a96f64929 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/support/management/micrometer/MicrometerMetricsCaptorImportSelector.java @@ -0,0 +1,42 @@ +/* + * Copyright 2021 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.integration.support.management.micrometer; + +import org.springframework.context.annotation.ImportSelector; +import org.springframework.core.type.AnnotationMetadata; + +/** + * An {@link ImportSelector} to conditionally add a {@link MicrometerMetricsCaptorConfiguration} + * bean when {@code io.micrometer.core.instrument.MeterRegistry} is present in classpath. + * + * @author Artem Bilan + * + * @since 5.5.5 + */ +public class MicrometerMetricsCaptorImportSelector implements ImportSelector { + + @Override + public String[] selectImports(AnnotationMetadata importingClassMetadata) { + if (MicrometerMetricsCaptorConfiguration.METER_REGISTRY_PRESENT) { + return new String[]{ MicrometerMetricsCaptorConfiguration.class.getName() }; + } + else { + return new String[0]; + } + } + +}