Re-instate lazy lookup for Binder in DestinationResolver
It's important not to depend on something heavyweight like a Binder in a BeanPostProcessor. The usual trick (as implemented here) is to do a lazy lookup of the thing that is eventually injected in the post processes beans. Fixes gh-82
This commit is contained in:
committed by
Marius Bogoevici
parent
dafa0fdf40
commit
15e3c6066f
@@ -17,31 +17,26 @@
|
||||
package org.springframework.cloud.stream.binder;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.integration.router.AbstractMappingMessageRouter;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.core.DestinationResolver;
|
||||
|
||||
/**
|
||||
* A {@link BeanPostProcessor} that sets a {@link BinderAwareChannelResolver} on any bean of type
|
||||
* {@link AbstractMappingMessageRouter} within the context.
|
||||
*
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Gary Russell
|
||||
*/
|
||||
public class BinderAwareRouterBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
|
||||
public class BinderAwareRouterBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private final BinderAwareChannelResolver channelResolver;
|
||||
private final DestinationResolver<MessageChannel> channelResolver;
|
||||
|
||||
public BinderAwareRouterBeanPostProcessor(BinderAwareChannelResolver channelResolver) {
|
||||
public BinderAwareRouterBeanPostProcessor(DestinationResolver<MessageChannel> channelResolver) {
|
||||
this.channelResolver = channelResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
channelResolver.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||
return bean;
|
||||
@@ -50,7 +45,7 @@ public class BinderAwareRouterBeanPostProcessor implements BeanPostProcessor, Be
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
if (bean instanceof AbstractMappingMessageRouter) {
|
||||
((AbstractMappingMessageRouter) bean).setChannelResolver(channelResolver);
|
||||
((AbstractMappingMessageRouter) bean).setChannelResolver(this.channelResolver);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ import org.springframework.cloud.stream.endpoint.ChannelsEndpoint;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.core.DestinationResolutionException;
|
||||
import org.springframework.messaging.core.DestinationResolver;
|
||||
|
||||
/**
|
||||
* Configuration class that provides necessary beans for {@link MessageChannel} binding.
|
||||
@@ -61,8 +63,9 @@ public class ChannelBindingAdapterConfiguration {
|
||||
|
||||
@Bean
|
||||
public ChannelBindingAdapter bindingAdapter() {
|
||||
ChannelBindingAdapter adapter = new ChannelBindingAdapter(this.module, this.binder);
|
||||
adapter.setChannelLocator(new DefaultChannelLocator(module));
|
||||
ChannelBindingAdapter adapter = new ChannelBindingAdapter(this.module,
|
||||
this.binder);
|
||||
adapter.setChannelLocator(new DefaultChannelLocator(this.module));
|
||||
adapter.setOutputChannels(getOutputChannels());
|
||||
adapter.setInputChannels(getInputChannels());
|
||||
adapter.setChannelResolver(binderAwareChannelResolver());
|
||||
@@ -81,7 +84,8 @@ public class ChannelBindingAdapterConfiguration {
|
||||
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition(name);
|
||||
// for now, just assume that the beans are at least AbstractBeanDefinition
|
||||
if (beanDefinition instanceof AbstractBeanDefinition
|
||||
&& ((AbstractBeanDefinition) beanDefinition).getQualifier(Output.class.getName()) != null) {
|
||||
&& ((AbstractBeanDefinition) beanDefinition)
|
||||
.getQualifier(Output.class.getName()) != null) {
|
||||
channels.add(new OutputChannelBinding(name));
|
||||
}
|
||||
}
|
||||
@@ -95,7 +99,8 @@ public class ChannelBindingAdapterConfiguration {
|
||||
BeanDefinition beanDefinition = this.beanFactory.getBeanDefinition(name);
|
||||
// for now, just assume that the beans are at least AbstractBeanDefinition
|
||||
if (beanDefinition instanceof AbstractBeanDefinition
|
||||
&& ((AbstractBeanDefinition) beanDefinition).getQualifier(Input.class.getName()) != null) {
|
||||
&& ((AbstractBeanDefinition) beanDefinition).getQualifier(Input.class
|
||||
.getName()) != null) {
|
||||
channels.add(new InputChannelBinding(name));
|
||||
}
|
||||
}
|
||||
@@ -104,11 +109,35 @@ public class ChannelBindingAdapterConfiguration {
|
||||
|
||||
@Bean
|
||||
public BinderAwareChannelResolver binderAwareChannelResolver() {
|
||||
return new BinderAwareChannelResolver(BeanFactoryUtils.beanOfType(beanFactory, Binder.class), new Properties());
|
||||
return new BinderAwareChannelResolver(this.binder, new Properties());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public BinderAwareRouterBeanPostProcessor binderAwareRouterBeanPostProcessor(BinderAwareChannelResolver resolver) {
|
||||
return new BinderAwareRouterBeanPostProcessor(resolver);
|
||||
// IMPORTANT: Nested class to avoid instantiating all of the above early
|
||||
@Configuration
|
||||
protected static class PostProcessorConfiguration {
|
||||
|
||||
private BinderAwareChannelResolver binderAwareChannelResolver;
|
||||
|
||||
@Bean
|
||||
public BinderAwareRouterBeanPostProcessor binderAwareRouterBeanPostProcessor(
|
||||
final ConfigurableListableBeanFactory beanFactory) {
|
||||
// IMPORTANT: Lazy delegate to avoid instantiating all of the above early
|
||||
return new BinderAwareRouterBeanPostProcessor(
|
||||
new DestinationResolver<MessageChannel>() {
|
||||
|
||||
@Override
|
||||
public MessageChannel resolveDestination(String name)
|
||||
throws DestinationResolutionException {
|
||||
if (PostProcessorConfiguration.this.binderAwareChannelResolver == null) {
|
||||
PostProcessorConfiguration.this.binderAwareChannelResolver = BeanFactoryUtils.beanOfType(
|
||||
beanFactory, BinderAwareChannelResolver.class);
|
||||
}
|
||||
return PostProcessorConfiguration.this.binderAwareChannelResolver.resolveDestination(name);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user