GH-2522 polishing previous commit
This commit is contained in:
@@ -36,13 +36,10 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.boot.Banner.Mode;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.cloud.function.context.FunctionCatalog;
|
||||
import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry;
|
||||
import org.springframework.cloud.stream.config.ListenerContainerCustomizer;
|
||||
import org.springframework.cloud.stream.config.SpelExpressionConverterConfiguration.SpelConverter;
|
||||
import org.springframework.cloud.stream.config.SpelExpressionConverterConfiguration;
|
||||
import org.springframework.cloud.stream.reflection.GenericsUtils;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -56,7 +53,6 @@ import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.core.io.UrlResource;
|
||||
import org.springframework.core.io.support.PropertiesLoaderUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
@@ -306,101 +302,16 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
.get(configurationName).getKey();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private ConfigurableApplicationContext initializeBinderContextBoot(String configurationName, Map<String, Object> binderProperties,
|
||||
BinderType binderType, BinderConfiguration binderConfiguration) {
|
||||
// Convert all properties to arguments, so that they receive maximum
|
||||
// // precedence
|
||||
ArrayList<String> args = new ArrayList<>();
|
||||
for (Map.Entry<String, Object> property : binderProperties.entrySet()) {
|
||||
args.add(
|
||||
String.format("--%s=%s", property.getKey(), property.getValue()));
|
||||
}
|
||||
// Initialize the domain with a unique name based on the bootstrapping context
|
||||
// setting
|
||||
ConfigurableEnvironment environment = this.context != null
|
||||
? this.context.getEnvironment() : null;
|
||||
String defaultDomain = environment != null
|
||||
? environment.getProperty("spring.jmx.default-domain") : "";
|
||||
args.add("--spring.jmx.default-domain=" + defaultDomain + "binder."
|
||||
+ configurationName);
|
||||
|
||||
SpringApplicationBuilder springApplicationBuilder = new SpringApplicationBuilder(
|
||||
binderType.getConfigurationClasses())
|
||||
.bannerMode(Mode.OFF).logStartupInfo(false)
|
||||
.web(WebApplicationType.NONE);
|
||||
// If the environment is not customized and a main context is available, we
|
||||
// will set the latter as parent.
|
||||
// This ensures that the defaults and user-defined customizations (e.g. custom
|
||||
// connection factory beans)
|
||||
// are propagated to the binder context. If the environment is customized,
|
||||
// then the binder context should
|
||||
// not inherit any beans from the parent
|
||||
boolean useApplicationContextAsParent = binderProperties.isEmpty()
|
||||
&& this.context != null;
|
||||
|
||||
if (useApplicationContextAsParent) {
|
||||
springApplicationBuilder.parent(this.context);
|
||||
}
|
||||
else {
|
||||
this.customizeParentChildContextRelationship(springApplicationBuilder, this.context);
|
||||
springApplicationBuilder.listeners(new ApplicationListener<ApplicationEvent>() {
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
if (context != null) {
|
||||
try {
|
||||
context.publishEvent(event);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Failed to publish " + event, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// If the current application context is not set as parent and the environment
|
||||
// is set,
|
||||
// provide the current context as an additional bean in the BeanFactory.
|
||||
if (environment != null && !useApplicationContextAsParent) {
|
||||
springApplicationBuilder
|
||||
.initializers(new InitializerWithOuterContext(this.context));
|
||||
}
|
||||
|
||||
if (environment != null && (useApplicationContextAsParent
|
||||
|| binderConfiguration.isInheritEnvironment())) {
|
||||
StandardEnvironment binderEnvironment = new StandardEnvironment();
|
||||
binderEnvironment.merge(environment);
|
||||
// See ConfigurationPropertySources.ATTACHED_PROPERTY_SOURCE_NAME
|
||||
binderEnvironment.getPropertySources().remove("configurationProperties");
|
||||
/*
|
||||
* Ensure that the web mode is set to NONE despite what the
|
||||
* parent application context says.
|
||||
* https://github.com/spring-cloud/spring-cloud-stream/issues/1708
|
||||
*/
|
||||
binderEnvironment.getPropertySources()
|
||||
.addFirst(new MapPropertySource("defaultBinderFactoryProperties",
|
||||
Collections.singletonMap("spring.main.web-application-type", "NONE")));
|
||||
|
||||
springApplicationBuilder.environment(binderEnvironment);
|
||||
}
|
||||
|
||||
ConfigurableApplicationContext binderProducingContext = springApplicationBuilder
|
||||
.run(args.toArray(new String[0]));
|
||||
return binderProducingContext;
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
private ConfigurableApplicationContext initializeBinderContextSimple(String configurationName, Map<String, Object> binderProperties,
|
||||
BinderType binderType, BinderConfiguration binderConfiguration) {
|
||||
//======= NEW CODE
|
||||
|
||||
AnnotationConfigApplicationContext binderProducingContext = new AnnotationConfigApplicationContext();
|
||||
if (this.context != null) {
|
||||
binderProducingContext.getBeanFactory().setConversionService(this.context.getBeanFactory().getConversionService());
|
||||
}
|
||||
|
||||
List<Class> sourceClasses = new ArrayList<>();
|
||||
sourceClasses.addAll(Arrays.asList(binderType.getConfigurationClasses()));
|
||||
sourceClasses.addAll(Collections.singletonList(SpelExpressionConverterConfiguration.class));
|
||||
if (binderProperties.containsKey("spring.main.sources")) {
|
||||
String sources = (String) binderProperties.get("spring.main.sources");
|
||||
if (StringUtils.hasText(sources)) {
|
||||
@@ -429,26 +340,6 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
else if (this.context != null) {
|
||||
this.propagateSharedBeans(binderProducingContext);
|
||||
Map<String, ListenerContainerCustomizer> customizers = this.context.getBeansOfType(ListenerContainerCustomizer.class);
|
||||
if (!CollectionUtils.isEmpty(customizers)) {
|
||||
for (Entry<String, ListenerContainerCustomizer> customizerEntry : customizers.entrySet()) {
|
||||
ListenerContainerCustomizer customizerWrapper = new ListenerContainerCustomizer() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void configure(Object container, String destinationName, String group) {
|
||||
try {
|
||||
customizerEntry.getValue().configure(container, destinationName, group);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Failed while applying ListenerContainerCustomizer. In situations when multiple "
|
||||
+ "binders are used this is expected, since a particular customizer may not be applicable.");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
((GenericApplicationContext) binderProducingContext).registerBean(customizerEntry.getKey(),
|
||||
ListenerContainerCustomizer.class, () -> customizerWrapper);
|
||||
}
|
||||
}
|
||||
binderProducingContext.addApplicationListener(new ApplicationListener<ApplicationEvent>() {
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEvent event) {
|
||||
@@ -523,48 +414,6 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a bare minimum application context that can be initialized by AOT.
|
||||
*
|
||||
* @param configurationName binder configuration name
|
||||
* @param binderProperties binder properties
|
||||
* @param binderConfiguration binder configuration
|
||||
* @return a binder child application context suitable for AOT initialization
|
||||
>>>>>>> 80e1e37a3... GH-2522 Add support for propagating select beans across child AC
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
private void customizeParentChildContextRelationship(SpringApplicationBuilder applicationBuilder, ApplicationContext context) {
|
||||
if (context != null) {
|
||||
Map<String, ListenerContainerCustomizer> customizers = context.getBeansOfType(ListenerContainerCustomizer.class);
|
||||
applicationBuilder.initializers(childContext -> {
|
||||
if (!CollectionUtils.isEmpty(customizers)) {
|
||||
for (Entry<String, ListenerContainerCustomizer> customizerEntry : customizers.entrySet()) {
|
||||
ListenerContainerCustomizer customizerWrapper = new ListenerContainerCustomizer() {
|
||||
@Override
|
||||
public void configure(Object container, String destinationName, String group) {
|
||||
try {
|
||||
customizerEntry.getValue().configure(container, destinationName, group);
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.warn("Failed while applying ListenerContainerCustomizer. In situations when multiple "
|
||||
+ "binders are used this is expected, since a particular customizer may not be applicable"
|
||||
+ "to a particular binder. Customizer: " + customizerEntry.getValue()
|
||||
+ " Binder: " + childContext.getBean(AbstractMessageChannelBinder.class), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
((GenericApplicationContext) childContext).registerBean(customizerEntry.getKey(),
|
||||
ListenerContainerCustomizer.class, () -> customizerWrapper);
|
||||
}
|
||||
}
|
||||
GenericConversionService cs = (GenericConversionService) ((GenericApplicationContext) childContext).getBeanFactory().getConversionService();
|
||||
SpelConverter spelConverter = new SpelConverter();
|
||||
cs.addConverter(spelConverter);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that nested properties are flattened (i.e., foo.bar=baz instead of
|
||||
* foo={bar=baz}).
|
||||
|
||||
@@ -22,11 +22,13 @@ 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.ConfigurableApplicationContext;
|
||||
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.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.ParseException;
|
||||
@@ -67,8 +69,13 @@ public class SpelExpressionConverterConfiguration {
|
||||
@Bean
|
||||
@ConfigurationPropertiesBinding
|
||||
@IntegrationConverter
|
||||
public Converter<String, Expression> spelConverter() {
|
||||
return new SpelConverter();
|
||||
public Converter<String, Expression> spelConverter(ConfigurableApplicationContext context) {
|
||||
SpelConverter converter = new SpelConverter();
|
||||
ConfigurableConversionService cs = (ConfigurableConversionService) context.getBeanFactory().getConversionService();
|
||||
if (cs != null) {
|
||||
cs.addConverter(converter);
|
||||
}
|
||||
return converter;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user