Introduce PollerMetadataCustomizer for Spring Integration

See gh-44637

Signed-off-by: Yanming Zhou <zhouyanming@gmail.com>
This commit is contained in:
Yanming Zhou 2025-03-07 15:54:15 +08:00 committed by Moritz Halbritter
parent 8a72a33051
commit 81048b42ca
3 changed files with 58 additions and 1 deletions

View File

@ -24,6 +24,7 @@ import javax.sql.DataSource;
import io.rsocket.transport.netty.server.TcpServerTransport;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
@ -85,6 +86,7 @@ import org.springframework.util.StringUtils;
* @author Vedran Pavic
* @author Madhura Bhave
* @author Yong-Hyun Kim
* @author Yanming Zhou
* @since 1.1.0
*/
@AutoConfiguration(after = { DataSourceAutoConfiguration.class, JmxAutoConfiguration.class,
@ -130,7 +132,8 @@ public class IntegrationAutoConfiguration {
@Bean(PollerMetadata.DEFAULT_POLLER)
@ConditionalOnMissingBean(name = PollerMetadata.DEFAULT_POLLER)
public PollerMetadata defaultPollerMetadata(IntegrationProperties integrationProperties) {
public PollerMetadata defaultPollerMetadata(IntegrationProperties integrationProperties,
ObjectProvider<PollerMetadataCustomizer> customizers) {
IntegrationProperties.Poller poller = integrationProperties.getPoller();
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
entries.put("spring.integration.poller.cron",
@ -143,6 +146,7 @@ public class IntegrationAutoConfiguration {
map.from(poller::getMaxMessagesPerPoll).to(pollerMetadata::setMaxMessagesPerPoll);
map.from(poller::getReceiveTimeout).as(Duration::toMillis).to(pollerMetadata::setReceiveTimeout);
map.from(poller).as(this::asTrigger).to(pollerMetadata::setTrigger);
customizers.orderedStream().forEach((customizer) -> customizer.customize(pollerMetadata));
return pollerMetadata;
}

View File

@ -0,0 +1,37 @@
/*
* 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.autoconfigure.integration;
import org.springframework.integration.scheduling.PollerMetadata;
/**
* Callback interface that can be implemented by beans wishing to customize the
* {@link PollerMetadata} whilst retaining default auto-configuration.
*
* @author Yanming Zhou
* @since 3.5.0
*/
@FunctionalInterface
public interface PollerMetadataCustomizer {
/**
* Customize the {@link PollerMetadata}.
* @param pollerMetadata the {@code PollerMetadata} to customize
*/
void customize(PollerMetadata pollerMetadata);
}

View File

@ -62,6 +62,8 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.SyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.integration.annotation.IntegrationComponentScan;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.annotation.ServiceActivator;
@ -105,6 +107,7 @@ import static org.mockito.Mockito.mock;
* @author Stephane Nicoll
* @author Vedran Pavic
* @author Yong-Hyun Kim
* @author Yanming Zhou
*/
class IntegrationAutoConfigurationTests {
@ -543,6 +546,19 @@ class IntegrationAutoConfigurationTests {
.usesVirtualThreads()));
}
@Test
void pollerMetadataCanBeCustomizedViaPollerMetadataCustomizer() {
TaskExecutor taskExecutor = new SyncTaskExecutor();
this.contextRunner.withUserConfiguration(PollingConsumerConfiguration.class)
.withBean(PollerMetadataCustomizer.class,
() -> (pollerMetadata) -> pollerMetadata.setTaskExecutor(taskExecutor))
.run((context) -> {
assertThat(context).hasSingleBean(PollerMetadata.class);
PollerMetadata metadata = context.getBean(PollerMetadata.DEFAULT_POLLER, PollerMetadata.class);
assertThat(metadata.getTaskExecutor()).isSameAs(taskExecutor);
});
}
@Configuration(proxyBeanMethods = false)
static class CustomMBeanExporter {