diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelInitializer.java b/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelInitializer.java
index e38bfce642..c1fb359af0 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelInitializer.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelInitializer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2022 the original author or authors.
+ * Copyright 2002-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.
@@ -25,17 +25,18 @@ import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.context.IntegrationContextUtils;
import org.springframework.util.Assert;
/**
- * A {@link InitializingBean} implementation that is responsible for creating
+ * An {@link InitializingBean} implementation that is responsible for creating
* channels that are not explicitly defined but identified via the 'input-channel'
* attribute of the corresponding endpoints.
- *
+ *
* This bean plays a role of pre-instantiator since it is instantiated and
- * initialized as the very first bean of all SI beans using
+ * initialized as the very first bean of all Spring Integration beans using
* {@link org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler}.
*
* @author Oleg Zhurakousky
@@ -48,7 +49,7 @@ public final class ChannelInitializer implements BeanFactoryAware, InitializingB
private static final Log LOGGER = LogFactory.getLog(ChannelInitializer.class);
- private volatile BeanFactory beanFactory;
+ private volatile DefaultListableBeanFactory beanFactory;
private volatile boolean autoCreate = true;
@@ -61,49 +62,38 @@ public final class ChannelInitializer implements BeanFactoryAware, InitializingB
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = beanFactory;
+ this.beanFactory = (DefaultListableBeanFactory) beanFactory;
}
@Override
public void afterPropertiesSet() {
Assert.notNull(this.beanFactory, "'beanFactory' must not be null");
- if (!this.autoCreate) {
- return;
- }
- else {
+ if (this.autoCreate) {
AutoCreateCandidatesCollector channelCandidatesCollector =
this.beanFactory.getBean(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME,
AutoCreateCandidatesCollector.class);
// at this point channelNames are all resolved with placeholders and SpEL
- Collection channelNames = channelCandidatesCollector.getChannelNames();
+ Collection channelNames = channelCandidatesCollector.channelNames;
if (channelNames != null) {
for (String channelName : channelNames) {
if (!this.beanFactory.containsBean(channelName)) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Auto-creating channel '" + channelName + "' as DirectChannel");
}
- IntegrationConfigUtils.autoCreateDirectChannel(channelName,
- (BeanDefinitionRegistry) this.beanFactory);
+ DirectChannel channelToRegister = new DirectChannel();
+ this.beanFactory.registerSingleton(channelName, channelToRegister);
+ this.beanFactory.initializeBean(channelToRegister, channelName);
}
}
}
}
}
- /*
- * Collects candidate channel names to be auto-created by ChannelInitializer
+ /**
+ * Collects candidate channel names to be auto-created by {@link ChannelInitializer}.
+ * @param channelNames the auto-create candidate channel bean names.
*/
- public static class AutoCreateCandidatesCollector {
-
- private final Collection channelNames;
-
- AutoCreateCandidatesCollector(Collection channelNames) {
- this.channelNames = channelNames;
- }
-
- public Collection getChannelNames() {
- return this.channelNames;
- }
+ public record AutoCreateCandidatesCollector(Collection channelNames) {
}
diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java
index f9642e6f22..9d194edd57 100644
--- a/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java
+++ b/spring-integration-core/src/main/java/org/springframework/integration/config/xml/AbstractConsumerEndpointParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-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.
@@ -29,6 +29,7 @@ import org.springframework.beans.factory.parsing.BeanComponentDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedSet;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
@@ -148,7 +149,7 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
String inputChannelName = element.getAttribute(inputChannelAttributeName);
if (!parserContext.getRegistry().containsBeanDefinition(inputChannelName)) {
- registerChannelForCreation(parserContext, inputChannelName);
+ registerChannelForCreation(parserContext, inputChannelName, builder);
}
IntegrationNamespaceUtils.checkAndConfigureFixedSubscriberChannel(element, parserContext, inputChannelName,
handlerBeanName);
@@ -177,12 +178,17 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
}
}
- private void registerChannelForCreation(ParserContext parserContext, String inputChannelName) {
- if (parserContext.getRegistry()
- .containsBeanDefinition(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME)) {
+ private void registerChannelForCreation(ParserContext parserContext, String inputChannelName,
+ BeanDefinitionBuilder consumerEndpointBuilder) {
- BeanDefinition channelRegistry = parserContext.getRegistry().
- getBeanDefinition(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
+ BeanDefinitionRegistry beanDefinitionRegistry = parserContext.getRegistry();
+
+ if (beanDefinitionRegistry.containsBeanDefinition(
+ IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME)) {
+
+ BeanDefinition channelRegistry =
+ beanDefinitionRegistry.getBeanDefinition(
+ IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
ConstructorArgumentValues caValues = channelRegistry.getConstructorArgumentValues();
ValueHolder vh = caValues.getArgumentValue(0, Collection.class);
if (vh == null) { //although it should never happen if it does we can fix it
@@ -194,11 +200,13 @@ public abstract class AbstractConsumerEndpointParser extends AbstractBeanDefinit
(Collection) caValues.getArgumentValue(0, Collection.class)
.getValue(); // NOSONAR see comment above
channelCandidateNames.add(inputChannelName); // NOSONAR
+
+ consumerEndpointBuilder.addDependsOn(IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME);
}
else {
parserContext.getReaderContext().error("Failed to locate '" +
IntegrationContextUtils.AUTO_CREATE_CHANNEL_CANDIDATES_BEAN_NAME + "'",
- parserContext.getRegistry());
+ beanDefinitionRegistry);
}
}