Some Java DSL improvements
* Register `BeanDefinition`s for DSL components. That way we get a gain when the `BeanDefinition` is involved, e.g. Spring Cloud Function uses this approach to determine the generics of the target `Function` class * This programmatic `BeanDefinition` registration approach (available since SF-5.0) allows us to avoid some manual lifecycle processes: bean initialization, autowiring, event listener registration etc. * Rework `IntegrationFlowContext` to register and remove `BeanDefinition`s as well * Remove unused `registerComponents` flag from the `StandardIntegrationFlow`. With the proper logic in the `IntegrationFlowContext` it does not make sense any more * Remove redundant `AnnotationGatewayProxyFactoryBean` in the `IntegrationFlows`; populate `defaultRequestChannel` directly to the `GatewayProxyFactoryBean` instance * Add an overloaded `IntegrationFlows.from(Class, String)` to allow to specify an explicit bean name for the target gateway proxy * Extract and populate bean name from the `@MessagingGateway.name()` in the `AnnotationGatewayProxyFactoryBean` * Stop lifecycles in the `AmqpTests` after using for proper test suit shutdown
This commit is contained in:
committed by
Gary Russell
parent
b69bbdc43b
commit
e6225926c4
@@ -40,6 +40,7 @@ import org.springframework.amqp.rabbit.listener.DirectMessageListenerContainer;
|
||||
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.amqp.channel.AbstractAmqpChannel;
|
||||
@@ -91,13 +92,19 @@ public class AmqpTests {
|
||||
@Qualifier("amqpInboundGatewayContainer")
|
||||
private SimpleMessageListenerContainer amqpInboundGatewayContainer;
|
||||
|
||||
@Autowired
|
||||
private Lifecycle asyncOutboundGateway;
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
brokerRunning.removeTestQueues();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAmqpInboundGatewayFlow() throws Exception {
|
||||
public void testAmqpInboundGatewayFlow() {
|
||||
assertNotNull(this.amqpInboundGatewayContainer);
|
||||
assertSame(this.amqpTemplate, TestUtils.getPropertyValue(this.amqpInboundGateway, "amqpTemplate"));
|
||||
|
||||
Object result = this.amqpTemplate.convertSendAndReceive(this.amqpQueue.getName(), "world");
|
||||
assertEquals("HELLO WORLD", result);
|
||||
|
||||
@@ -109,9 +116,6 @@ public class AmqpTests {
|
||||
((RabbitTemplate) this.amqpTemplate).setReceiveTimeout(10000);
|
||||
result = this.amqpTemplate.receiveAndConvert("defaultReplyTo");
|
||||
assertEquals("HELLO WORLD", result);
|
||||
assertSame(this.amqpTemplate, TestUtils.getPropertyValue(this.amqpInboundGateway, "amqpTemplate"));
|
||||
|
||||
assertNotNull(this.amqpInboundGatewayContainer);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@@ -141,6 +145,8 @@ public class AmqpTests {
|
||||
|
||||
assertNotNull(receive);
|
||||
assertEquals("HELLO THROUGH THE AMQP", receive.getPayload());
|
||||
|
||||
((Lifecycle) this.amqpOutboundInput).stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -167,6 +173,8 @@ public class AmqpTests {
|
||||
Message<?> receive = replyChannel.receive(10000);
|
||||
assertNotNull(receive);
|
||||
assertEquals("HELLO ASYNC GATEWAY", receive.getPayload());
|
||||
|
||||
this.asyncOutboundGateway.stop();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@@ -264,7 +272,8 @@ public class AmqpTests {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow amqpInboundFlow(ConnectionFactory rabbitConnectionFactory) {
|
||||
return IntegrationFlows.from(Amqp.inboundAdapter(rabbitConnectionFactory, fooQueue()))
|
||||
return IntegrationFlows.from(Amqp.inboundAdapter(rabbitConnectionFactory, fooQueue())
|
||||
.id("amqpInboundFlowAdapter"))
|
||||
.transform(String.class, String::toUpperCase)
|
||||
.channel(Amqp.pollableChannel(rabbitConnectionFactory)
|
||||
.queueName("amqpReplyChannel")
|
||||
@@ -286,7 +295,8 @@ public class AmqpTests {
|
||||
public IntegrationFlow amqpAsyncOutboundFlow(AsyncRabbitTemplate asyncRabbitTemplate) {
|
||||
return f -> f
|
||||
.handle(Amqp.asyncOutboundGateway(asyncRabbitTemplate)
|
||||
.routingKeyFunction(m -> queue().getName()));
|
||||
.routingKeyFunction(m -> queue().getName()),
|
||||
e -> e.id("asyncOutboundGateway"));
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -17,26 +17,23 @@
|
||||
package org.springframework.integration.config.dsl;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanCreationNotAllowedException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.SmartInitializingSingleton;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ApplicationEventMulticaster;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.core.io.DescriptiveResource;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.channel.DirectChannel;
|
||||
import org.springframework.integration.channel.FixedSubscriberChannel;
|
||||
@@ -67,17 +64,14 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Artem Bilan
|
||||
* @author Gary Russell
|
||||
*
|
||||
* @since 5.0
|
||||
*/
|
||||
public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware,
|
||||
SmartInitializingSingleton {
|
||||
|
||||
private final Set<ApplicationListener<?>> applicationListeners = new HashSet<ApplicationListener<?>>();
|
||||
public class IntegrationFlowBeanPostProcessor
|
||||
implements BeanPostProcessor, BeanFactoryAware, SmartInitializingSingleton {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
Assert.isInstanceOf(ConfigurableListableBeanFactory.class, beanFactory,
|
||||
@@ -86,8 +80,6 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
);
|
||||
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
this.autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
|
||||
this.autowiredAnnotationBeanPostProcessor.setBeanFactory(this.beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,13 +103,6 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
|
||||
@Override
|
||||
public void afterSingletonsInstantiated() {
|
||||
if (this.beanFactory.containsBean(AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
|
||||
ApplicationEventMulticaster multicaster =
|
||||
(ApplicationEventMulticaster) this.beanFactory.getBean(
|
||||
AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME);
|
||||
this.applicationListeners.forEach(multicaster::addApplicationListener);
|
||||
}
|
||||
|
||||
for (String beanName : this.beanFactory.getBeanNamesForType(IntegrationFlow.class)) {
|
||||
if (this.beanFactory.containsBeanDefinition(beanName)) {
|
||||
String scope = this.beanFactory.getBeanDefinition(beanName).getScope();
|
||||
@@ -135,8 +120,6 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
String flowNamePrefix = flowBeanName + ".";
|
||||
int subFlowNameIndex = 0;
|
||||
int channelNameIndex = 0;
|
||||
boolean registerSingleton = flow.isRegisterComponents();
|
||||
|
||||
|
||||
Map<Object, String> integrationComponents = flow.getIntegrationComponents();
|
||||
Map<Object, String> targetIntegrationComponents = new LinkedHashMap<>(integrationComponents.size());
|
||||
@@ -161,13 +144,13 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
String handlerBeanName = generateBeanName(messageHandler);
|
||||
String[] handlerAlias = new String[] { id + IntegrationConfigUtils.HANDLER_ALIAS_SUFFIX };
|
||||
|
||||
registerComponent(messageHandler, handlerBeanName, flowBeanName, registerSingleton);
|
||||
registerComponent(messageHandler, handlerBeanName, flowBeanName);
|
||||
for (String alias : handlerAlias) {
|
||||
this.beanFactory.registerAlias(handlerBeanName, alias);
|
||||
}
|
||||
}
|
||||
|
||||
registerComponent(endpoint, id, flowBeanName, registerSingleton);
|
||||
registerComponent(endpoint, id, flowBeanName);
|
||||
targetIntegrationComponents.put(endpoint, id);
|
||||
}
|
||||
else {
|
||||
@@ -182,14 +165,14 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + channelNameIndex++;
|
||||
}
|
||||
}
|
||||
registerComponent(component, channelBeanName, flowBeanName, registerSingleton);
|
||||
registerComponent(component, channelBeanName, flowBeanName);
|
||||
targetIntegrationComponents.put(component, channelBeanName);
|
||||
}
|
||||
else if (component instanceof MessageChannelReference) {
|
||||
String channelBeanName = ((MessageChannelReference) component).getName();
|
||||
if (!this.beanFactory.containsBean(channelBeanName)) {
|
||||
DirectChannel directChannel = new DirectChannel();
|
||||
registerComponent(directChannel, channelBeanName, flowBeanName, registerSingleton);
|
||||
registerComponent(directChannel, channelBeanName, flowBeanName);
|
||||
targetIntegrationComponents.put(directChannel, channelBeanName);
|
||||
}
|
||||
}
|
||||
@@ -200,7 +183,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
channelBeanName = flowNamePrefix + "channel" +
|
||||
BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + channelNameIndex++;
|
||||
}
|
||||
registerComponent(component, channelBeanName, flowBeanName, registerSingleton);
|
||||
registerComponent(component, channelBeanName, flowBeanName);
|
||||
targetIntegrationComponents.put(component, channelBeanName);
|
||||
}
|
||||
else if (component instanceof SourcePollingChannelAdapterSpec) {
|
||||
@@ -221,7 +204,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = generateBeanName(pollingChannelAdapterFactoryBean, entry.getValue());
|
||||
}
|
||||
registerComponent(pollingChannelAdapterFactoryBean, id, flowBeanName, registerSingleton);
|
||||
registerComponent(pollingChannelAdapterFactoryBean, id, flowBeanName);
|
||||
targetIntegrationComponents.put(pollingChannelAdapterFactoryBean, id);
|
||||
|
||||
MessageSource<?> messageSource = spec.get().getT2();
|
||||
@@ -233,7 +216,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
&& ((NamedComponent) messageSource).getComponentName() != null) {
|
||||
messageSourceId = ((NamedComponent) messageSource).getComponentName();
|
||||
}
|
||||
registerComponent(messageSource, messageSourceId, flowBeanName, registerSingleton);
|
||||
registerComponent(messageSource, messageSourceId, flowBeanName);
|
||||
}
|
||||
}
|
||||
else if (component instanceof StandardIntegrationFlow) {
|
||||
@@ -242,19 +225,31 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
? entry.getValue()
|
||||
: flowNamePrefix + "subFlow" +
|
||||
BeanFactoryUtils.GENERATED_BEAN_NAME_SEPARATOR + subFlowNameIndex++;
|
||||
registerComponent(component, subFlowBeanName, flowBeanName, registerSingleton);
|
||||
registerComponent(component, subFlowBeanName, flowBeanName);
|
||||
targetIntegrationComponents.put(component, subFlowBeanName);
|
||||
}
|
||||
else if (component instanceof AnnotationGatewayProxyFactoryBean) {
|
||||
String gatewayId = entry.getValue() != null
|
||||
? entry.getValue()
|
||||
: flowNamePrefix + "gateway";
|
||||
registerComponent(component, gatewayId, flowBeanName, registerSingleton);
|
||||
AnnotationGatewayProxyFactoryBean gateway = (AnnotationGatewayProxyFactoryBean) component;
|
||||
String gatewayId = entry.getValue();
|
||||
|
||||
if (gatewayId == null) {
|
||||
gatewayId = gateway.getComponentName();
|
||||
}
|
||||
if (gatewayId == null) {
|
||||
gatewayId = flowNamePrefix + "gateway";
|
||||
}
|
||||
|
||||
registerComponent(gateway, gatewayId, flowBeanName,
|
||||
beanDefinition -> {
|
||||
((AbstractBeanDefinition) beanDefinition)
|
||||
.setSource(new DescriptiveResource(gateway.getObjectType().getName()));
|
||||
});
|
||||
|
||||
targetIntegrationComponents.put(component, gatewayId);
|
||||
}
|
||||
else {
|
||||
String generatedBeanName = generateBeanName(component, entry.getValue());
|
||||
registerComponent(component, generatedBeanName, flowBeanName, registerSingleton);
|
||||
registerComponent(component, generatedBeanName, flowBeanName);
|
||||
targetIntegrationComponents.put(component, generatedBeanName);
|
||||
}
|
||||
}
|
||||
@@ -276,7 +271,7 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
}
|
||||
|
||||
private void processIntegrationComponentSpec(IntegrationComponentSpec<?, ?> bean) {
|
||||
registerComponent(bean.get(), generateBeanName(bean.get(), bean.getId()), null, false);
|
||||
registerComponent(bean.get(), generateBeanName(bean.get(), bean.getId()));
|
||||
if (bean instanceof ComponentsRegistration) {
|
||||
Map<Object, String> componentsToRegister = ((ComponentsRegistration) bean).getComponentsToRegister();
|
||||
if (!CollectionUtils.isEmpty(componentsToRegister)) {
|
||||
@@ -296,26 +291,25 @@ public class IntegrationFlowBeanPostProcessor implements BeanPostProcessor, Bean
|
||||
}
|
||||
|
||||
private void registerComponent(Object component, String beanName) {
|
||||
registerComponent(component, beanName, null, true);
|
||||
registerComponent(component, beanName, null);
|
||||
}
|
||||
|
||||
private void registerComponent(Object component, String beanName, String parentName, boolean registerSingleton) {
|
||||
if (component instanceof ApplicationListener) {
|
||||
this.applicationListeners.add((ApplicationListener<?>) component);
|
||||
}
|
||||
this.autowiredAnnotationBeanPostProcessor.processInjection(component);
|
||||
this.beanFactory.initializeBean(component, beanName);
|
||||
if (registerSingleton) {
|
||||
this.beanFactory.registerSingleton(beanName, component);
|
||||
if (parentName != null) {
|
||||
this.beanFactory.registerDependentBean(parentName, beanName);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
private void registerComponent(Object component, String beanName, String parentName,
|
||||
BeanDefinitionCustomizer... customizers) {
|
||||
|
||||
BeanDefinition beanDefinition =
|
||||
BeanDefinitionBuilder.genericBeanDefinition((Class<Object>) component.getClass(), () -> component)
|
||||
.applyCustomizers(customizers)
|
||||
.getRawBeanDefinition();
|
||||
|
||||
((BeanDefinitionRegistry) this.beanFactory).registerBeanDefinition(beanName, beanDefinition);
|
||||
|
||||
if (parentName != null) {
|
||||
this.beanFactory.registerDependentBean(parentName, beanName);
|
||||
}
|
||||
|
||||
if (component instanceof DisposableBean) {
|
||||
((DefaultSingletonBeanRegistry) this.beanFactory)
|
||||
.registerDisposableBean(beanName, (DisposableBean) component);
|
||||
}
|
||||
this.beanFactory.getBean(beanName);
|
||||
}
|
||||
|
||||
private String generateBeanName(Object instance) {
|
||||
|
||||
@@ -302,28 +302,38 @@ public final class IntegrationFlows {
|
||||
* Populate the {@link MessageChannel} to the new {@link IntegrationFlowBuilder}
|
||||
* chain, which becomes as a {@code requestChannel} for the Messaging Gateway(s) built
|
||||
* on the provided service interface.
|
||||
* <p>A gateway proxy bean for provided service interface is registered under a name of
|
||||
* the {@link IntegrationFlow} bean plus {@code .gateway} suffix.
|
||||
* <p>A gateway proxy bean for provided service interface is registered under a name
|
||||
* from the
|
||||
* {@link org.springframework.integration.annotation.MessagingGateway#name()} if present
|
||||
* or from the {@link IntegrationFlow} bean name plus {@code .gateway} suffix.
|
||||
* @param serviceInterface the service interface class with an optional
|
||||
* {@link org.springframework.integration.annotation.MessagingGateway} annotation.
|
||||
* @return new {@link IntegrationFlowBuilder}.
|
||||
*/
|
||||
public static IntegrationFlowBuilder from(Class<?> serviceInterface) {
|
||||
return from(serviceInterface, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the {@link MessageChannel} to the new {@link IntegrationFlowBuilder}
|
||||
* chain, which becomes as a {@code requestChannel} for the Messaging Gateway(s) built
|
||||
* on the provided service interface.
|
||||
* <p>A gateway proxy bean for provided service interface is registered under a name of
|
||||
* the provided {@code beanName} if not null, or from the
|
||||
* {@link org.springframework.integration.annotation.MessagingGateway#name()} if present
|
||||
* or as a fallback to the {@link IntegrationFlow} bean name plus {@code .gateway} suffix.
|
||||
* @param serviceInterface the service interface class with an optional
|
||||
* {@link org.springframework.integration.annotation.MessagingGateway} annotation.
|
||||
* @param beanName the bean name to be used for registering bean for the gateway proxy
|
||||
* @return new {@link IntegrationFlowBuilder}.
|
||||
*/
|
||||
public static IntegrationFlowBuilder from(Class<?> serviceInterface, String beanName) {
|
||||
final DirectChannel gatewayRequestChannel = new DirectChannel();
|
||||
|
||||
GatewayProxyFactoryBean gatewayProxyFactoryBean =
|
||||
new AnnotationGatewayProxyFactoryBean(serviceInterface) {
|
||||
GatewayProxyFactoryBean gatewayProxyFactoryBean = new AnnotationGatewayProxyFactoryBean(serviceInterface);
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
getGateways()
|
||||
.values()
|
||||
.forEach(gateway ->
|
||||
gateway.setRequestChannel(gatewayRequestChannel));
|
||||
}
|
||||
|
||||
};
|
||||
gatewayProxyFactoryBean.setDefaultRequestChannel(gatewayRequestChannel);
|
||||
gatewayProxyFactoryBean.setBeanName(beanName);
|
||||
|
||||
return from(gatewayRequestChannel)
|
||||
.addComponent(gatewayProxyFactoryBean);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
* Copyright 2016-2017 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.
|
||||
@@ -69,23 +69,12 @@ public class StandardIntegrationFlow implements IntegrationFlow, SmartLifecycle
|
||||
|
||||
private final List<SmartLifecycle> lifecycles = new LinkedList<>();
|
||||
|
||||
private final boolean registerComponents = true; // NOSONAR
|
||||
|
||||
private boolean running;
|
||||
|
||||
StandardIntegrationFlow(Map<Object, String> integrationComponents) {
|
||||
this.integrationComponents = new LinkedHashMap<>(integrationComponents);
|
||||
}
|
||||
|
||||
//TODO Figure out some custom DestinationResolver when we don't register singletons - remove NOSONAR above when done
|
||||
/*public void setRegisterComponents(boolean registerComponents) {
|
||||
this.registerComponents = registerComponents;
|
||||
}*/
|
||||
|
||||
public boolean isRegisterComponents() {
|
||||
return this.registerComponents;
|
||||
}
|
||||
|
||||
public void setIntegrationComponents(Map<Object, String> integrationComponents) {
|
||||
this.integrationComponents.clear();
|
||||
this.integrationComponents.putAll(integrationComponents);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.integration.dsl.context;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -24,10 +25,10 @@ import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.DefaultSingletonBeanRegistry;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.dsl.IntegrationFlow;
|
||||
import org.springframework.integration.support.context.NamedComponent;
|
||||
@@ -68,8 +69,6 @@ public final class IntegrationFlowContext implements BeanFactoryAware {
|
||||
|
||||
private ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
private AutowiredAnnotationBeanPostProcessor autowiredAnnotationBeanPostProcessor;
|
||||
|
||||
private IntegrationFlowContext() {
|
||||
}
|
||||
|
||||
@@ -80,8 +79,6 @@ public final class IntegrationFlowContext implements BeanFactoryAware {
|
||||
"'ConfigurableListableBeanFactory'. " +
|
||||
"Consider using 'GenericApplicationContext' implementation.");
|
||||
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
|
||||
this.autowiredAnnotationBeanPostProcessor = new AutowiredAnnotationBeanPostProcessor();
|
||||
this.autowiredAnnotationBeanPostProcessor.setBeanFactory(this.beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,22 +110,23 @@ public final class IntegrationFlowContext implements BeanFactoryAware {
|
||||
this.registry.put(flowId, builder.integrationFlowRegistration);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object registerBean(Object bean, String beanName, String parentName) {
|
||||
if (beanName == null) {
|
||||
beanName = generateBeanName(bean, parentName);
|
||||
}
|
||||
|
||||
this.autowiredAnnotationBeanPostProcessor.processInjection(bean);
|
||||
bean = this.beanFactory.initializeBean(bean, beanName);
|
||||
this.beanFactory.registerSingleton(beanName, bean);
|
||||
BeanDefinition beanDefinition =
|
||||
BeanDefinitionBuilder.genericBeanDefinition((Class<Object>) bean.getClass(), () -> bean)
|
||||
.getRawBeanDefinition();
|
||||
|
||||
((BeanDefinitionRegistry) this.beanFactory).registerBeanDefinition(beanName, beanDefinition);
|
||||
|
||||
if (parentName != null) {
|
||||
this.beanFactory.registerDependentBean(parentName, beanName);
|
||||
}
|
||||
if (bean instanceof DisposableBean) {
|
||||
((DefaultSingletonBeanRegistry) this.beanFactory)
|
||||
.registerDisposableBean(beanName, (DisposableBean) bean);
|
||||
}
|
||||
return bean;
|
||||
|
||||
return this.beanFactory.getBean(beanName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -150,7 +148,11 @@ public final class IntegrationFlowContext implements BeanFactoryAware {
|
||||
if (this.registry.containsKey(flowId)) {
|
||||
IntegrationFlowRegistration flowRegistration = this.registry.remove(flowId);
|
||||
flowRegistration.stop();
|
||||
((DefaultSingletonBeanRegistry) this.beanFactory).destroySingleton(flowId);
|
||||
|
||||
Arrays.stream(this.beanFactory.getDependentBeans(flowId))
|
||||
.forEach(((BeanDefinitionRegistry) this.beanFactory)::removeBeanDefinition);
|
||||
|
||||
((BeanDefinitionRegistry) this.beanFactory).removeBeanDefinition(flowId);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Only manually registered IntegrationFlows can be removed. "
|
||||
@@ -207,7 +209,7 @@ public final class IntegrationFlowContext implements BeanFactoryAware {
|
||||
|
||||
private boolean autoStartup = true;
|
||||
|
||||
IntegrationFlowRegistrationBuilder(IntegrationFlow integrationFlow) {
|
||||
private IntegrationFlowRegistrationBuilder(IntegrationFlow integrationFlow) {
|
||||
this.integrationFlowRegistration = new IntegrationFlowRegistration(integrationFlow);
|
||||
this.integrationFlowRegistration.setBeanFactory(IntegrationFlowContext.this.beanFactory);
|
||||
this.integrationFlowRegistration.setIntegrationFlowContext(IntegrationFlowContext.this);
|
||||
|
||||
@@ -47,13 +47,20 @@ public class AnnotationGatewayProxyFactoryBean extends GatewayProxyFactoryBean {
|
||||
|
||||
public AnnotationGatewayProxyFactoryBean(Class<?> serviceInterface) {
|
||||
super(serviceInterface);
|
||||
AnnotationAttributes gatewayAttributes = AnnotatedElementUtils.getMergedAnnotationAttributes(serviceInterface,
|
||||
MessagingGateway.class.getName(), false, true);
|
||||
AnnotationAttributes gatewayAttributes =
|
||||
AnnotatedElementUtils.getMergedAnnotationAttributes(serviceInterface,
|
||||
MessagingGateway.class.getName(), false, true);
|
||||
if (gatewayAttributes == null) {
|
||||
gatewayAttributes = AnnotationUtils.getAnnotationAttributes(
|
||||
AnnotationUtils.synthesizeAnnotation(MessagingGateway.class), false, true);
|
||||
}
|
||||
|
||||
this.gatewayAttributes = gatewayAttributes;
|
||||
|
||||
String id = gatewayAttributes.getString("name");
|
||||
if (!StringUtils.hasText(id)) {
|
||||
setBeanName(id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -444,6 +444,7 @@ public class IntegrationFlowTests {
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Qualifier("errorRecovererFunction")
|
||||
private Function<String, String> errorRecovererFlowGateway;
|
||||
|
||||
@Test
|
||||
@@ -789,7 +790,7 @@ public class IntegrationFlowTests {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow errorRecovererFlow() {
|
||||
return IntegrationFlows.from(Function.class)
|
||||
return IntegrationFlows.from(Function.class, "errorRecovererFunction")
|
||||
.handle((GenericHandler<?>) (p, h) -> {
|
||||
throw new RuntimeException("intentional");
|
||||
}, e -> e.advice(retryAdvice()))
|
||||
|
||||
Reference in New Issue
Block a user