Native compilation changes required in SCSt apps
- Instead of injecting `AbstractMappingMessageRouter[]`, inject it as a container type using `List<>`. This is because the former uses reflection behind the scenes and causes issues with graal native compilation (unless provided as a native hint). - Instead of autowiring `Map<String, BindingTargetFactory>` in `AbstractBindableProxyFactory`, programmatically populate `BindingTargetFactory` beans by doing a `BeanFactory` lookup in a new method. Then the subclasses of `AbstractBindableProxyFactory` call this method to pouplate the avaialble `BindingTargetFactory` beans in their `afterPropertiesSet` method. - Convert array injection of `BindableProxyFactory[]` in functionInitailzer bean in `FunctionConfiguration` to use container based injejction (`List<>`). - Cleanup unused injection in functionInitializer bean in `FunctionConfiguration`. Resolves https://github.com/spring-cloud/spring-cloud-stream/issues/2154 Resolves #2155
This commit is contained in:
committed by
Oleg Zhurakousky
parent
1cd165df46
commit
ae017e222f
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2019 the original author or authors.
|
||||
* Copyright 2019-2021 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.
|
||||
@@ -26,7 +26,8 @@ import java.util.Set;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.cloud.stream.binder.Binding;
|
||||
import org.springframework.cloud.stream.internal.InternalPropertyNames;
|
||||
@@ -48,7 +49,6 @@ public class AbstractBindableProxyFactory implements Bindable {
|
||||
@Value("${" + InternalPropertyNames.NAMESPACE_PROPERTY_NAME + ":}")
|
||||
private String namespace;
|
||||
|
||||
@Autowired
|
||||
protected Map<String, BindingTargetFactory> bindingTargetFactories;
|
||||
|
||||
protected Map<String, BoundTargetHolder> inputHolders = new LinkedHashMap<>();
|
||||
@@ -57,10 +57,16 @@ public class AbstractBindableProxyFactory implements Bindable {
|
||||
|
||||
protected Class<?> type;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public AbstractBindableProxyFactory(Class<?> type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
protected void populateBindingTargetFactories(BeanFactory beanFactory) {
|
||||
this.bindingTargetFactories = ((ListableBeanFactory) beanFactory).getBeansOfType(BindingTargetFactory.class);
|
||||
}
|
||||
|
||||
protected BindingTargetFactory getBindingTargetFactory(Class<?> bindingTargetType) {
|
||||
List<String> candidateBindingTargetFactories = new ArrayList<>();
|
||||
for (Map.Entry<String, BindingTargetFactory> bindingTargetFactoryEntry : this.bindingTargetFactories
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2019 the original author or authors.
|
||||
* Copyright 2015-2021 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.
|
||||
@@ -26,6 +26,9 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.cloud.stream.annotation.EnableBinding;
|
||||
@@ -45,10 +48,11 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author David Syer
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Soby Chacko
|
||||
* @see EnableBinding
|
||||
*/
|
||||
public class BindableProxyFactory extends AbstractBindableProxyFactory
|
||||
implements MethodInterceptor, FactoryBean<Object>, InitializingBean {
|
||||
implements MethodInterceptor, FactoryBean<Object>, InitializingBean, BeanFactoryAware {
|
||||
|
||||
private static Log log = LogFactory.getLog(BindableProxyFactory.class);
|
||||
|
||||
@@ -56,6 +60,8 @@ public class BindableProxyFactory extends AbstractBindableProxyFactory
|
||||
|
||||
private Object proxy;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public BindableProxyFactory(Class<?> type) {
|
||||
super(type);
|
||||
this.type = type;
|
||||
@@ -112,6 +118,7 @@ public class BindableProxyFactory extends AbstractBindableProxyFactory
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
populateBindingTargetFactories(this.beanFactory);
|
||||
Assert.notEmpty(BindableProxyFactory.this.bindingTargetFactories,
|
||||
"'bindingTargetFactories' cannot be empty");
|
||||
ReflectionUtils.doWithMethods(this.type, method -> {
|
||||
@@ -159,4 +166,8 @@ public class BindableProxyFactory extends AbstractBindableProxyFactory
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2019 the original author or authors.
|
||||
* Copyright 2015-2021 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.
|
||||
@@ -170,6 +170,7 @@ public class BinderFactoryAutoConfiguration {
|
||||
ClassLoader classLoader = configurableApplicationContext.getClassLoader();
|
||||
try {
|
||||
Enumeration<URL> resources = classLoader.getResources("META-INF/spring.binders");
|
||||
|
||||
// see if test binder is available on the classpath and if so add it to the binderTypes
|
||||
try {
|
||||
BinderType bt = new BinderType("integration", new Class[] {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2018 the original author or authors.
|
||||
* Copyright 2015-2021 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.
|
||||
@@ -70,6 +70,7 @@ import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.core.DestinationResolver;
|
||||
import org.springframework.scheduling.TaskScheduler;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -198,7 +199,6 @@ public class BindingServiceConfiguration {
|
||||
public BinderFactory binderFactory(BinderTypeRegistry binderTypeRegistry,
|
||||
BindingServiceProperties bindingServiceProperties,
|
||||
ObjectProvider<BinderCustomizer> binderCustomizerProvider) {
|
||||
|
||||
DefaultBinderFactory binderFactory = new DefaultBinderFactory(
|
||||
getBinderConfigurations(binderTypeRegistry, bindingServiceProperties),
|
||||
binderTypeRegistry, binderCustomizerProvider.getIfUnique());
|
||||
@@ -271,11 +271,12 @@ public class BindingServiceConfiguration {
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public BinderAwareRouter binderAwareRouterBeanPostProcessor(
|
||||
@Autowired(required = false) AbstractMappingMessageRouter[] routers,
|
||||
@Autowired(required = false) List<AbstractMappingMessageRouter> routers,
|
||||
@Autowired(required = false) @Qualifier("binderAwareChannelResolver")
|
||||
DestinationResolver<MessageChannel> channelResolver) {
|
||||
|
||||
return new BinderAwareRouter(routers, channelResolver);
|
||||
final AbstractMappingMessageRouter[] routersArray = CollectionUtils.isEmpty(routers) ?
|
||||
new AbstractMappingMessageRouter[]{} : routers.toArray(new AbstractMappingMessageRouter[]{});
|
||||
return new BinderAwareRouter(routersArray, channelResolver);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019-2019 the original author or authors.
|
||||
* Copyright 2019-2021 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.
|
||||
@@ -39,6 +39,7 @@ import org.springframework.util.CollectionUtils;
|
||||
* function with the name `myFunction`.
|
||||
*
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Soby Chacko
|
||||
*
|
||||
* @since 3.0
|
||||
*/
|
||||
@@ -74,6 +75,7 @@ class BindableFunctionProxyFactory extends BindableProxyFactory {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
populateBindingTargetFactories(context.getBeanFactory());
|
||||
Assert.notEmpty(BindableFunctionProxyFactory.this.bindingTargetFactories,
|
||||
"'bindingTargetFactories' cannot be empty");
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2018-2020 the original author or authors.
|
||||
* Copyright 2018-2021 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.
|
||||
@@ -116,6 +116,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Oleg Zhurakousky
|
||||
* @author David Turanski
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Soby Chacko
|
||||
* @since 2.1
|
||||
*/
|
||||
@Configuration
|
||||
@@ -147,10 +148,10 @@ public class FunctionConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public InitializingBean functionInitializer(FunctionCatalog functionCatalog, FunctionInspector functionInspector,
|
||||
StreamFunctionProperties functionProperties, @Nullable BindableProxyFactory[] bindableProxyFactories,
|
||||
BindingServiceProperties serviceProperties, ConfigurableApplicationContext applicationContext,
|
||||
FunctionBindingRegistrar bindingHolder, StreamBridge streamBridge) {
|
||||
public InitializingBean functionInitializer(FunctionCatalog functionCatalog,
|
||||
StreamFunctionProperties functionProperties,
|
||||
BindingServiceProperties serviceProperties, ConfigurableApplicationContext applicationContext,
|
||||
StreamBridge streamBridge) {
|
||||
|
||||
boolean shouldCreateInitializer = applicationContext.containsBean("output")
|
||||
|| ObjectUtils.isEmpty(applicationContext.getBeanNamesForAnnotation(EnableBinding.class));
|
||||
@@ -167,10 +168,10 @@ public class FunctionConfiguration {
|
||||
@Bean
|
||||
InitializingBean supplierInitializer(FunctionCatalog functionCatalog, StreamFunctionProperties functionProperties,
|
||||
GenericApplicationContext context, BindingServiceProperties serviceProperties,
|
||||
@Nullable BindableFunctionProxyFactory[] proxyFactories, StreamBridge streamBridge,
|
||||
@Nullable List<BindableFunctionProxyFactory> proxyFactories, StreamBridge streamBridge,
|
||||
TaskScheduler taskScheduler) {
|
||||
|
||||
if (!ObjectUtils.isEmpty(context.getBeanNamesForAnnotation(EnableBinding.class)) || proxyFactories == null) {
|
||||
if (!ObjectUtils.isEmpty(context.getBeanNamesForAnnotation(EnableBinding.class)) || CollectionUtils.isEmpty(proxyFactories)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user