Ensure that condition evaluator uses runner’s class loader

Closes gh-13319
pull/13388/head
Andy Wilkinson 7 years ago
parent 152ce145fd
commit 27267a7090

@ -196,9 +196,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
} }
/** /**
* Customize the {@link ClassLoader} that the {@link ApplicationContext} should use. * Customize the {@link ClassLoader} that the {@link ApplicationContext} should use
* Customizing the {@link ClassLoader} is an effective manner to hide resources from * for resource loading and bean class loading.
* the classpath.
* @param classLoader the classloader to use (can be null to use the default) * @param classLoader the classloader to use (can be null to use the default)
* @return a new instance with the updated class loader * @return a new instance with the updated class loader
* @see FilteredClassLoader * @see FilteredClassLoader
@ -274,15 +273,34 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SELF run(ContextConsumer<? super A> consumer) { public SELF run(ContextConsumer<? super A> consumer) {
this.systemProperties.applyToSystemProperties(() -> { withContextClassLoader(this.classLoader, () -> {
try (A context = createAssertableContext()) { this.systemProperties.applyToSystemProperties(() -> {
accept(consumer, context); try (A context = createAssertableContext()) {
} accept(consumer, context);
return null; }
return null;
});
}); });
return (SELF) this; return (SELF) this;
} }
private void withContextClassLoader(ClassLoader classLoader, Runnable action) {
if (classLoader == null) {
action.run();
}
else {
Thread currentThread = Thread.currentThread();
ClassLoader previous = currentThread.getContextClassLoader();
currentThread.setContextClassLoader(classLoader);
try {
action.run();
}
finally {
currentThread.setContextClassLoader(previous);
}
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private A createAssertableContext() { private A createAssertableContext() {
ResolvableType resolvableType = ResolvableType ResolvableType resolvableType = ResolvableType

@ -30,8 +30,12 @@ import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.assertj.ApplicationContextAssertProvider; import org.springframework.boot.test.context.assertj.ApplicationContextAssertProvider;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment; import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -150,7 +154,7 @@ public abstract class AbstractApplicationContextRunnerTests<T extends AbstractAp
} }
@Test @Test
public void runWithClassLoaderShouldSetClassLoader() { public void runWithClassLoaderShouldSetClassLoaderOnContext() {
get().withClassLoader(new FilteredClassLoader(Gson.class.getPackage().getName())) get().withClassLoader(new FilteredClassLoader(Gson.class.getPackage().getName()))
.run((context) -> { .run((context) -> {
try { try {
@ -164,6 +168,14 @@ public abstract class AbstractApplicationContextRunnerTests<T extends AbstractAp
}); });
} }
@Test
public void runWithClassLoaderShouldSetClassLoaderOnConditionContext() {
get().withClassLoader(new FilteredClassLoader(Gson.class.getPackage().getName()))
.withUserConfiguration(ConditionalConfig.class)
.run((context) -> assertThat(context)
.hasSingleBean(ConditionalConfig.class));
}
@Test @Test
public void thrownRuleWorksWithCheckedException() { public void thrownRuleWorksWithCheckedException() {
get().run((context) -> { get().run((context) -> {
@ -209,4 +221,19 @@ public abstract class AbstractApplicationContextRunnerTests<T extends AbstractAp
} }
@Configuration
@Conditional(FilteredClassLoaderCondition.class)
static class ConditionalConfig {
}
static class FilteredClassLoaderCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getClassLoader() instanceof FilteredClassLoader;
}
}
} }

Loading…
Cancel
Save