Commit e306aad2 authored by Andy Wilkinson's avatar Andy Wilkinson

Merge branch '2.0.x'

parents 68c10ea0 27267a70
...@@ -196,9 +196,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl ...@@ -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 ...@@ -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) {
withContextClassLoader(this.classLoader, () -> {
this.systemProperties.applyToSystemProperties(() -> { this.systemProperties.applyToSystemProperties(() -> {
try (A context = createAssertableContext()) { try (A context = createAssertableContext()) {
accept(consumer, context); 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; ...@@ -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 ...@@ -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 ...@@ -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 ...@@ -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;
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment