GH-1272 Removal of parent/child context
Initial removal of parent/child context for Binders. This commit contains bare minimum of what's required while still supporting 'the old way'.
Basically implementor of a binder must do the following things:
- name your configuration file as the usual boot 'spring.factories` (no more spring.binders)
- add name attribute to the `@Bean` which declares the actual binders (e.g., `@Bean('rabbit')`)
This PR ensures that the existing functionality (the use of spring.binders) is preserved.
Resolves #1272
Resolves #1361
polishing
This commit is contained in:
committed by
Soby Chacko
parent
7be8ea59e9
commit
66254ca9f6
@@ -19,6 +19,7 @@ package org.springframework.cloud.stream.binder;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -48,6 +49,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author Marius Bogoevici
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Gary Russell
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class DefaultBinderFactory implements BinderFactory, DisposableBean, ApplicationContextAware {
|
||||
|
||||
@@ -91,8 +93,35 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
this.defaultBinderForBindingTargetType.clear();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
@Override
|
||||
public synchronized <T> Binder<T, ?, ?> getBinder(String name, Class<? extends T> bindingTargetType) {
|
||||
|
||||
String binderName = StringUtils.hasText(name) ? name : this.defaultBinder;
|
||||
|
||||
Map<String, Binder> binders = this.context == null ? Collections.emptyMap() : this.context.getBeansOfType(Binder.class);
|
||||
Binder<T, ConsumerProperties, ProducerProperties> binder;
|
||||
if (StringUtils.hasText(binderName) && binders.containsKey(binderName)) {
|
||||
binder = (Binder<T, ConsumerProperties, ProducerProperties>) this.context.getBean(binderName);
|
||||
}
|
||||
else if (binders.size() == 1) {
|
||||
binder = binders.values().iterator().next();
|
||||
}
|
||||
else if (binders.size() > 1) {
|
||||
throw new IllegalStateException("Multiple binders are available, however neither default nor "
|
||||
+ "per-destination binder name is provided. Available binders are " + binders.keySet());
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* This is the fall back to the old bootstrap that relies on spring.binders.
|
||||
*/
|
||||
binder = this.doGetBinder(binderName, bindingTargetType);
|
||||
}
|
||||
return binder;
|
||||
}
|
||||
|
||||
|
||||
private <T> Binder<T, ConsumerProperties, ProducerProperties> doGetBinder(String name, Class<? extends T> bindingTargetType) {
|
||||
String configurationName;
|
||||
// Fall back to a default if no argument is provided
|
||||
if (StringUtils.isEmpty(name)) {
|
||||
@@ -136,7 +165,7 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
else {
|
||||
configurationName = name;
|
||||
}
|
||||
Binder<T, ?, ?> binderInstance = getBinderInstance(configurationName);
|
||||
Binder<T, ConsumerProperties, ProducerProperties> binderInstance = getBinderInstance(configurationName);
|
||||
Assert.state(verifyBinderTypeMatchesTarget(binderInstance, bindingTargetType),
|
||||
"The binder '" + configurationName + "' cannot bind a " + bindingTargetType.getName());
|
||||
return binderInstance;
|
||||
@@ -159,7 +188,7 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Binder<T, ?, ?> getBinderInstance(String configurationName) {
|
||||
private <T> Binder<T, ConsumerProperties, ProducerProperties> getBinderInstance(String configurationName) {
|
||||
if (!this.binderInstanceCache.containsKey(configurationName)) {
|
||||
BinderConfiguration binderConfiguration = this.binderConfigurations.get(configurationName);
|
||||
Assert.state(binderConfiguration != null, "Unknown binder configuration: " + configurationName);
|
||||
@@ -212,7 +241,7 @@ public class DefaultBinderFactory implements BinderFactory, DisposableBean, Appl
|
||||
}
|
||||
this.binderInstanceCache.put(configurationName, new SimpleImmutableEntry<>(binder, binderProducingContext));
|
||||
}
|
||||
return (Binder<T, ?, ?>) this.binderInstanceCache.get(configurationName).getKey();
|
||||
return (Binder<T, ConsumerProperties, ProducerProperties>) this.binderInstanceCache.get(configurationName).getKey();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2018 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.
|
||||
@@ -27,6 +27,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
@@ -52,11 +55,14 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* @author Marius Bogoevici
|
||||
* @author Ilayaperumal Gopinathan
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
@Configuration
|
||||
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
|
||||
public class BinderFactoryConfiguration {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private static final String SPRING_CLOUD_STREAM_INTERNAL_PREFIX = "spring.cloud.stream.internal";
|
||||
|
||||
private static final String SELF_CONTAINED_APP_PROPERTY_NAME = SPRING_CLOUD_STREAM_INTERNAL_PREFIX
|
||||
@@ -150,16 +156,19 @@ public class BinderFactoryConfiguration {
|
||||
try {
|
||||
Enumeration<URL> resources = classLoader.getResources("META-INF/spring.binders");
|
||||
if (!Boolean.valueOf(this.selfContained) && (resources == null || !resources.hasMoreElements())) {
|
||||
throw new BeanCreationException("Cannot create binder factory, no `META-INF/spring.binders` " +
|
||||
"resources found on the classpath");
|
||||
this.logger.debug("Failed to locate 'META-INF/spring.binders' resources on the classpath."
|
||||
+ " Assuming standard boot 'META-INF/spring.factories' configuration is used");
|
||||
}
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
UrlResource resource = new UrlResource(url);
|
||||
for (BinderType binderType : parseBinderConfigurations(classLoader, resource)) {
|
||||
binderTypes.put(binderType.getDefaultName(), binderType);
|
||||
else {
|
||||
while (resources.hasMoreElements()) {
|
||||
URL url = resources.nextElement();
|
||||
UrlResource resource = new UrlResource(url);
|
||||
for (BinderType binderType : parseBinderConfigurations(classLoader, resource)) {
|
||||
binderTypes.put(binderType.getDefaultName(), binderType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (IOException | ClassNotFoundException e) {
|
||||
throw new BeanCreationException("Cannot create binder factory:", e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2017 the original author or authors.
|
||||
* Copyright 2015-2018 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.
|
||||
@@ -22,7 +22,6 @@ import java.net.URLClassLoader;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.boot.WebApplicationType;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
@@ -82,33 +81,6 @@ public class BinderFactoryConfigurationTests {
|
||||
.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadBinderTypeRegistry() throws Exception {
|
||||
try {
|
||||
createBinderTestContext(new String[] {});
|
||||
fail();
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getMessage()).contains(
|
||||
"Cannot create binder factory, no `META-INF/spring.binders` resources found on the classpath");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadBinderTypeRegistryWithNonSelfContainedAggregatorApp() throws Exception {
|
||||
try {
|
||||
createBinderTestContextWithSources(
|
||||
new Class[] { SimpleApplication.class }, new String[] {},
|
||||
"spring.cloud.stream.internal.selfContained=false");
|
||||
fail();
|
||||
}
|
||||
catch (BeanCreationException e) {
|
||||
assertThat(e.getMessage()).contains(
|
||||
"Cannot create binder factory, no `META-INF/spring.binders` resources found on the classpath");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loadBinderTypeRegistryWithSelfContainedAggregatorApp() throws Exception {
|
||||
createBinderTestContextWithSources(
|
||||
|
||||
Reference in New Issue
Block a user