Support LoadBalancer child context creation during AOT processing (#1135)
This commit is contained in:
committed by
GitHub
parent
6e610bf5c9
commit
94ab8728fb
@@ -24,6 +24,7 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.springframework.aot.AotDetector;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -35,8 +36,11 @@ import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigRegistry;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Creates a set of child contexts that allows a set of Specifications to define the beans
|
||||
@@ -48,8 +52,8 @@ import org.springframework.core.env.MapPropertySource;
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Tommy Karlsson
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
// TODO: add javadoc
|
||||
public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
|
||||
implements DisposableBean, ApplicationContextAware {
|
||||
|
||||
@@ -57,7 +61,7 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
|
||||
private final String propertyName;
|
||||
|
||||
private Map<String, AnnotationConfigApplicationContext> contexts = new ConcurrentHashMap<>();
|
||||
private final Map<String, GenericApplicationContext> contexts = new ConcurrentHashMap<>();
|
||||
|
||||
private Map<String, C> configurations = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -92,8 +96,8 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
Collection<AnnotationConfigApplicationContext> values = this.contexts.values();
|
||||
for (AnnotationConfigApplicationContext context : values) {
|
||||
Collection<GenericApplicationContext> values = this.contexts.values();
|
||||
for (GenericApplicationContext context : values) {
|
||||
// This can fail, but it never throws an exception (you see stack traces
|
||||
// logged as WARN).
|
||||
context.close();
|
||||
@@ -101,7 +105,7 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
this.contexts.clear();
|
||||
}
|
||||
|
||||
protected AnnotationConfigApplicationContext getContext(String name) {
|
||||
protected GenericApplicationContext getContext(String name) {
|
||||
if (!this.contexts.containsKey(name)) {
|
||||
synchronized (this.contexts) {
|
||||
if (!this.contexts.containsKey(name)) {
|
||||
@@ -112,8 +116,39 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
return this.contexts.get(name);
|
||||
}
|
||||
|
||||
protected AnnotationConfigApplicationContext createContext(String name) {
|
||||
AnnotationConfigApplicationContext context;
|
||||
public void addContext(String contextId, GenericApplicationContext context) {
|
||||
Assert.notNull(contextId, "contextId cannot be null.");
|
||||
Assert.notNull(context, "context cannot be null.");
|
||||
contexts.put(contextId, context);
|
||||
}
|
||||
|
||||
public GenericApplicationContext createContext(String name) {
|
||||
GenericApplicationContext context = buildContext(name);
|
||||
registerBeans(name, context);
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
public void registerBeans(String name, GenericApplicationContext context) {
|
||||
Assert.isInstanceOf(AnnotationConfigRegistry.class, context);
|
||||
AnnotationConfigRegistry registry = (AnnotationConfigRegistry) context;
|
||||
if (this.configurations.containsKey(name)) {
|
||||
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
|
||||
registry.register(configuration);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
|
||||
if (entry.getKey().startsWith("default.")) {
|
||||
for (Class<?> configuration : entry.getValue().getConfiguration()) {
|
||||
registry.register(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
registry.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
|
||||
}
|
||||
|
||||
public GenericApplicationContext buildContext(String name) {
|
||||
GenericApplicationContext context;
|
||||
if (this.parent != null) {
|
||||
// jdk11 issue
|
||||
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
|
||||
@@ -126,33 +161,21 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
else {
|
||||
beanFactory.setBeanClassLoader(parent.getClassLoader());
|
||||
}
|
||||
context = new AnnotationConfigApplicationContext(beanFactory);
|
||||
context.setClassLoader(this.parent.getClassLoader());
|
||||
context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext(beanFactory)
|
||||
: new AnnotationConfigApplicationContext(beanFactory);
|
||||
context.setClassLoader(parent.getClassLoader());
|
||||
}
|
||||
else {
|
||||
context = new AnnotationConfigApplicationContext();
|
||||
context = AotDetector.useGeneratedArtifacts() ? new GenericApplicationContext()
|
||||
: new AnnotationConfigApplicationContext();
|
||||
}
|
||||
if (this.configurations.containsKey(name)) {
|
||||
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
|
||||
context.register(configuration);
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
|
||||
if (entry.getKey().startsWith("default.")) {
|
||||
for (Class<?> configuration : entry.getValue().getConfiguration()) {
|
||||
context.register(configuration);
|
||||
}
|
||||
}
|
||||
}
|
||||
context.register(PropertyPlaceholderAutoConfiguration.class, this.defaultConfigType);
|
||||
context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(this.propertySourceName,
|
||||
Collections.<String, Object>singletonMap(this.propertyName, name)));
|
||||
context.getEnvironment().getPropertySources().addFirst(
|
||||
new MapPropertySource(this.propertySourceName, Collections.singletonMap(this.propertyName, name)));
|
||||
if (this.parent != null) {
|
||||
// Uses Environment from parent as well as beans
|
||||
context.setParent(this.parent);
|
||||
}
|
||||
context.setDisplayName(generateDisplayName(name));
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -161,7 +184,7 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
}
|
||||
|
||||
public <T> T getInstance(String name, Class<T> type) {
|
||||
AnnotationConfigApplicationContext context = getContext(name);
|
||||
GenericApplicationContext context = getContext(name);
|
||||
try {
|
||||
return context.getBean(type);
|
||||
}
|
||||
@@ -176,7 +199,7 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
}
|
||||
|
||||
public <T> ObjectProvider<T> getProvider(String name, Class<T> type) {
|
||||
AnnotationConfigApplicationContext context = getContext(name);
|
||||
GenericApplicationContext context = getContext(name);
|
||||
return context.getBeanProvider(type);
|
||||
}
|
||||
|
||||
@@ -187,7 +210,7 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getInstance(String name, ResolvableType type) {
|
||||
AnnotationConfigApplicationContext context = getContext(name);
|
||||
GenericApplicationContext context = getContext(name);
|
||||
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, type);
|
||||
if (beanNames.length > 0) {
|
||||
for (String beanName : beanNames) {
|
||||
@@ -200,11 +223,15 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
}
|
||||
|
||||
public <T> Map<String, T> getInstances(String name, Class<T> type) {
|
||||
AnnotationConfigApplicationContext context = getContext(name);
|
||||
GenericApplicationContext context = getContext(name);
|
||||
|
||||
return BeanFactoryUtils.beansOfTypeIncludingAncestors(context, type);
|
||||
}
|
||||
|
||||
public Map<String, C> getConfigurations() {
|
||||
return configurations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specification with name and configuration.
|
||||
*/
|
||||
|
||||
@@ -38,6 +38,7 @@ import static org.assertj.core.api.BDDAssertions.then;
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Tommy Karlsson
|
||||
* @author Olga Maciaszek-Sharma
|
||||
*/
|
||||
public class NamedContextFactoryTests {
|
||||
|
||||
@@ -86,8 +87,8 @@ public class NamedContextFactoryTests {
|
||||
then(barBazes.size()).as("barBazes size was wrong").isEqualTo(2);
|
||||
|
||||
// get the contexts before destroy() to verify these are the old ones
|
||||
AnnotationConfigApplicationContext fooContext = factory.getContext("foo");
|
||||
AnnotationConfigApplicationContext barContext = factory.getContext("bar");
|
||||
GenericApplicationContext fooContext = factory.getContext("foo");
|
||||
GenericApplicationContext barContext = factory.getContext("bar");
|
||||
|
||||
then(fooContext.getClassLoader()).as("foo context classloader does not match parent")
|
||||
.isSameAs(parent.getClassLoader());
|
||||
|
||||
Reference in New Issue
Block a user