Merge remote-tracking branch 'origin/3.1.x'
This commit is contained in:
@@ -29,9 +29,11 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.ObjectProvider;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
@@ -45,6 +47,7 @@ import org.springframework.core.env.MapPropertySource;
|
||||
* @param <C> specification
|
||||
* @author Spencer Gibb
|
||||
* @author Dave Syer
|
||||
* @author Tommy Karlsson
|
||||
*/
|
||||
// TODO: add javadoc
|
||||
public abstract class NamedContextFactory<C extends NamedContextFactory.Specification>
|
||||
@@ -110,7 +113,25 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
}
|
||||
|
||||
protected AnnotationConfigApplicationContext createContext(String name) {
|
||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
AnnotationConfigApplicationContext context;
|
||||
if (this.parent != null) {
|
||||
// jdk11 issue
|
||||
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
|
||||
// https://github.com/spring-cloud/spring-cloud-openfeign/issues/475
|
||||
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
|
||||
if (parent instanceof ConfigurableApplicationContext) {
|
||||
beanFactory.setBeanClassLoader(
|
||||
((ConfigurableApplicationContext) parent).getBeanFactory().getBeanClassLoader());
|
||||
}
|
||||
else {
|
||||
beanFactory.setBeanClassLoader(parent.getClassLoader());
|
||||
}
|
||||
context = new AnnotationConfigApplicationContext(beanFactory);
|
||||
context.setClassLoader(this.parent.getClassLoader());
|
||||
}
|
||||
else {
|
||||
context = new AnnotationConfigApplicationContext();
|
||||
}
|
||||
if (this.configurations.containsKey(name)) {
|
||||
for (Class<?> configuration : this.configurations.get(name).getConfiguration()) {
|
||||
context.register(configuration);
|
||||
@@ -129,9 +150,6 @@ public abstract class NamedContextFactory<C extends NamedContextFactory.Specific
|
||||
if (this.parent != null) {
|
||||
// Uses Environment from parent as well as beans
|
||||
context.setParent(this.parent);
|
||||
// jdk11 issue
|
||||
// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
|
||||
context.setClassLoader(this.parent.getClassLoader());
|
||||
}
|
||||
context.setDisplayName(generateDisplayName(name));
|
||||
context.refresh();
|
||||
|
||||
@@ -18,17 +18,26 @@ package org.springframework.cloud.context.named;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
/**
|
||||
* @author Spencer Gibb
|
||||
* @author Tommy Karlsson
|
||||
*/
|
||||
public class NamedContextFactoryTests {
|
||||
|
||||
@@ -37,6 +46,10 @@ public class NamedContextFactoryTests {
|
||||
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
|
||||
parent.register(BaseConfig.class);
|
||||
parent.refresh();
|
||||
testChildContexts(parent);
|
||||
}
|
||||
|
||||
private void testChildContexts(GenericApplicationContext parent) {
|
||||
TestClientFactory factory = new TestClientFactory();
|
||||
factory.setApplicationContext(parent);
|
||||
factory.setConfigurations(Arrays.asList(getSpec("foo", FooConfig.class), getSpec("bar", BarConfig.class)));
|
||||
@@ -79,6 +92,10 @@ public class NamedContextFactoryTests {
|
||||
then(fooContext.getClassLoader()).as("foo context classloader does not match parent")
|
||||
.isSameAs(parent.getClassLoader());
|
||||
|
||||
then(fooContext.getBeanFactory().getBeanClassLoader())
|
||||
.as("foo context bean factory classloader does not match parent")
|
||||
.isSameAs(parent.getBeanFactory().getBeanClassLoader());
|
||||
|
||||
Assertions.assertThat(fooContext).hasFieldOrPropertyWithValue("customClassLoader", true);
|
||||
|
||||
factory.destroy();
|
||||
@@ -88,10 +105,39 @@ public class NamedContextFactoryTests {
|
||||
then(barContext.isActive()).as("bar context wasn't closed").isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBadThreadContextClassLoader() throws InterruptedException, ExecutionException, TimeoutException {
|
||||
AnnotationConfigApplicationContext parent = new AnnotationConfigApplicationContext();
|
||||
parent.setClassLoader(ClassUtils.getDefaultClassLoader());
|
||||
parent.register(BaseConfig.class);
|
||||
parent.refresh();
|
||||
|
||||
ExecutorService es = Executors.newSingleThreadExecutor(r -> {
|
||||
Thread t = new Thread(r);
|
||||
t.setContextClassLoader(new ThrowingClassLoader());
|
||||
return t;
|
||||
});
|
||||
|
||||
es.submit(() -> this.testChildContexts(parent)).get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
private TestSpec getSpec(String name, Class<?> configClass) {
|
||||
return new TestSpec(name, new Class[] { configClass });
|
||||
}
|
||||
|
||||
static class ThrowingClassLoader extends ClassLoader {
|
||||
|
||||
ThrowingClassLoader() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> loadClass(String name) throws ClassNotFoundException {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestClientFactory extends NamedContextFactory<TestSpec> {
|
||||
|
||||
TestClientFactory() {
|
||||
@@ -147,6 +193,7 @@ public class NamedContextFactoryTests {
|
||||
|
||||
}
|
||||
|
||||
@ConditionalOnClass(Object.class)
|
||||
static class FooConfig {
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user