From f53ff9585abcec5cf80be6cadc30cf25246e004e Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 27 Nov 2017 09:21:13 -0500 Subject: [PATCH] 1146 Initial fix for eager initialization in StreamListenerAnnotationBPP - Removed dependency and callbacks to 'BeanFactoryUtils.beansOfTypeIncludingAncestors' in StreamListenerAnnotationBeanPostProcessor in favor of more appropriate and lazy DI mechanism provided by Spring. - Polishing --- ...amListenerAnnotationBeanPostProcessor.java | 38 +++++-------------- .../config/BinderFactoryConfiguration.java | 3 ++ .../config/BindingServiceConfiguration.java | 9 +++++ .../config/ContentTypeConfiguration.java | 3 ++ .../SpelExpressionConverterConfiguration.java | 3 ++ 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java index 38ae2e617..73fe421c5 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/binding/StreamListenerAnnotationBeanPostProcessor.java @@ -26,9 +26,7 @@ import org.springframework.aop.support.AopUtils; 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.BeanInitializationException; -import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; @@ -74,16 +72,19 @@ import org.springframework.util.StringUtils; * @author Oleg Zhurakousky */ public class StreamListenerAnnotationBeanPostProcessor - implements BeanPostProcessor, ApplicationContextAware, BeanFactoryAware, SmartInitializingSingleton, - InitializingBean { + implements BeanPostProcessor, ApplicationContextAware, BeanFactoryAware, SmartInitializingSingleton { private static final SpelExpressionParser SPEL_EXPRESSION_PARSER = new SpelExpressionParser(); private final MultiValueMap mappedListenerMethods = new LinkedMultiValueMap<>(); - private final List> streamListenerParameterAdapters = new ArrayList<>(); + @Autowired(required=false) + @Lazy + private List> streamListenerParameterAdapters; - private final List> streamListenerResultAdapters = new ArrayList<>(); + @Autowired(required=false) + @Lazy + private List> streamListenerResultAdapters; @Autowired @Lazy @@ -120,27 +121,6 @@ public class StreamListenerAnnotationBeanPostProcessor } } - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Override - public void afterPropertiesSet() throws Exception { - Map parameterAdapterMap = BeanFactoryUtils - .beansOfTypeIncludingAncestors(this.applicationContext, StreamListenerParameterAdapter.class); - for (StreamListenerParameterAdapter parameterAdapter : parameterAdapterMap.values()) { - this.streamListenerParameterAdapters.add(parameterAdapter); - } - Map resultAdapterMap = BeanFactoryUtils - .beansOfTypeIncludingAncestors(this.applicationContext, StreamListenerResultAdapter.class); - this.streamListenerResultAdapters.add(new MessageChannelStreamListenerResultAdapter()); - for (StreamListenerResultAdapter resultAdapter : resultAdapterMap.values()) { - this.streamListenerResultAdapters.add(resultAdapter); - } - } - - @Override - public final Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - @Override public final Object postProcessAfterInitialization(final Object bean, final String beanName) throws BeansException { Class targetClass = AopUtils.isAopProxy(bean) ? AopUtils.getTargetClass(bean) : bean.getClass(); @@ -243,7 +223,7 @@ public class StreamListenerAnnotationBeanPostProcessor if (!this.streamListenerParameterAdapters.isEmpty()) { try { Object targetBean = this.applicationContext.getBean(targetBeanName); - for (StreamListenerParameterAdapter streamListenerParameterAdapter : this.streamListenerParameterAdapters) { + for (StreamListenerParameterAdapter streamListenerParameterAdapter : this.streamListenerParameterAdapters) { if (streamListenerParameterAdapter.supports(targetBean.getClass(), methodParameter)) { return true; } @@ -277,7 +257,7 @@ public class StreamListenerAnnotationBeanPostProcessor Assert.isInstanceOf(String.class, targetReferenceValue, "Annotation value must be a String"); Object targetBean = this.applicationContext.getBean((String) targetReferenceValue); // Iterate existing parameter adapters first - for (StreamListenerParameterAdapter streamListenerParameterAdapter : this.streamListenerParameterAdapters) { + for (StreamListenerParameterAdapter streamListenerParameterAdapter : this.streamListenerParameterAdapters) { if (streamListenerParameterAdapter.supports(targetBean.getClass(), methodParameter)) { arguments[parameterIndex] = streamListenerParameterAdapter.adapt(targetBean, methodParameter); break; diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderFactoryConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderFactoryConfiguration.java index 1c1e38e27..12f329bde 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderFactoryConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BinderFactoryConfiguration.java @@ -30,6 +30,7 @@ import java.util.Properties; import org.springframework.beans.factory.BeanCreationException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.cloud.stream.binder.BinderConfiguration; import org.springframework.cloud.stream.binder.BinderFactory; @@ -40,6 +41,7 @@ import org.springframework.cloud.stream.binder.DefaultBinderTypeRegistry; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; import org.springframework.core.io.Resource; import org.springframework.core.io.UrlResource; import org.springframework.core.io.support.PropertiesLoaderUtils; @@ -52,6 +54,7 @@ import org.springframework.util.StringUtils; * @author Ilayaperumal Gopinathan */ @Configuration +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class BinderFactoryConfiguration { private static final String SPRING_CLOUD_STREAM_INTERNAL_PREFIX = "spring.cloud.stream.internal"; diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java index 721179ff8..45f2c0acd 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/BindingServiceConfiguration.java @@ -25,6 +25,7 @@ import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -41,6 +42,7 @@ import org.springframework.cloud.stream.binding.ContextStartAfterRefreshListener import org.springframework.cloud.stream.binding.DynamicDestinationsBindable; import org.springframework.cloud.stream.binding.InputBindingLifecycle; import org.springframework.cloud.stream.binding.MessageChannelConfigurer; +import org.springframework.cloud.stream.binding.MessageChannelStreamListenerResultAdapter; import org.springframework.cloud.stream.binding.MessageConverterConfigurer; import org.springframework.cloud.stream.binding.OutputBindingLifecycle; import org.springframework.cloud.stream.binding.SingleBindingTargetBindable; @@ -51,6 +53,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.Role; import org.springframework.expression.PropertyAccessor; import org.springframework.integration.channel.DirectChannel; import org.springframework.integration.channel.PublishSubscribeChannel; @@ -82,6 +85,7 @@ import org.springframework.tuple.spel.TuplePropertyAccessor; @Configuration @EnableConfigurationProperties({ BindingServiceProperties.class, SpringIntegrationProperties.class }) @Import(ContentTypeConfiguration.class) +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class BindingServiceConfiguration { public static final String STREAM_LISTENER_ANNOTATION_BEAN_POST_PROCESSOR_NAME = @@ -91,6 +95,11 @@ public class BindingServiceConfiguration { private static final String ERROR_KEY_NAME = "error"; + @Bean + public MessageChannelStreamListenerResultAdapter messageChannelStreamListenerResultAdapter() { + return new MessageChannelStreamListenerResultAdapter(); + } + @Bean public static MessageHandlerMethodFactory messageHandlerMethodFactory( CompositeMessageConverterFactory compositeMessageConverterFactory) { diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ContentTypeConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ContentTypeConfiguration.java index 72a0a452a..d1fb4dce9 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ContentTypeConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/ContentTypeConfiguration.java @@ -23,10 +23,12 @@ import java.util.List; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.cloud.stream.annotation.StreamMessageConverter; import org.springframework.cloud.stream.converter.CompositeMessageConverterFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Role; import org.springframework.integration.context.IntegrationContextUtils; import org.springframework.integration.support.converter.ConfigurableCompositeMessageConverter; import org.springframework.messaging.converter.MessageConverter; @@ -36,6 +38,7 @@ import org.springframework.util.CollectionUtils; * @author Vinicius Carvalho */ @Configuration +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class ContentTypeConfiguration { @Autowired(required = false) diff --git a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java index d33a416be..699f1a861 100644 --- a/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java +++ b/spring-cloud-stream/src/main/java/org/springframework/cloud/stream/config/SpelExpressionConverterConfiguration.java @@ -18,10 +18,12 @@ package org.springframework.cloud.stream.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.boot.context.properties.ConfigurationPropertiesBinding; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Lazy; +import org.springframework.context.annotation.Role; import org.springframework.core.convert.converter.Converter; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; @@ -37,6 +39,7 @@ import org.springframework.integration.context.IntegrationContextUtils; * @author Eric Bottard */ @Configuration +@Role(BeanDefinition.ROLE_INFRASTRUCTURE) public class SpelExpressionConverterConfiguration { @Bean