Skip to content

Commit

Permalink
Disable bean overriding by default in ApplicationContextRunner
Browse files Browse the repository at this point in the history
For consistency with SpringApplication, this commit disables bean
overriding by default in ApplicationContextRunner. Bean overriding can
be enabled again using withAllowBeanDefinitionOverriding.

Closes gh-18019
  • Loading branch information
snicoll committed Jan 28, 2020
1 parent e92e818 commit eb852f1
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 63 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand Down Expand Up @@ -35,7 +35,8 @@
*/
class WebMvcEndpointChildContextConfigurationTests {

private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner();
private WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
.withAllowBeanDefinitionOverriding(true);

@Test
void contextShouldConfigureRequestContextFilter() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand Down Expand Up @@ -136,8 +136,8 @@ private void hasBarBean(AssertableApplicationContext context) {

@Test
void conditionEvaluationConsidersChangeInTypeWhenBeanIsOverridden() {
this.contextRunner.withUserConfiguration(OriginalDefinition.class, OverridingDefinition.class,
ConsumingConfiguration.class).run((context) -> {
this.contextRunner.withAllowBeanDefinitionOverriding(true).withUserConfiguration(OriginalDefinition.class,
OverridingDefinition.class, ConsumingConfiguration.class).run((context) -> {
assertThat(context).hasBean("testBean");
assertThat(context).hasSingleBean(Integer.class);
assertThat(context).doesNotHaveBean(ConsumingConfiguration.class);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand All @@ -25,7 +25,9 @@

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.context.annotation.Configurations;
import org.springframework.boot.context.annotation.UserConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
Expand Down Expand Up @@ -105,6 +107,8 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl

private final Supplier<C> contextFactory;

private final boolean allowBeanDefinitionOverriding;

private final List<ApplicationContextInitializer<? super C>> initializers;

private final TestPropertyValues environmentProperties;
Expand All @@ -124,13 +128,14 @@ public abstract class AbstractApplicationContextRunner<SELF extends AbstractAppl
* @param contextFactory the factory used to create the actual context
*/
protected AbstractApplicationContextRunner(Supplier<C> contextFactory) {
this(contextFactory, Collections.emptyList(), TestPropertyValues.empty(), TestPropertyValues.empty(), null,
null, Collections.emptyList(), Collections.emptyList());
this(contextFactory, false, Collections.emptyList(), TestPropertyValues.empty(), TestPropertyValues.empty(),
null, null, Collections.emptyList(), Collections.emptyList());
}

/**
* Create a new {@link AbstractApplicationContextRunner} instance.
* @param contextFactory the factory used to create the actual context
* @param allowBeanDefinitionOverriding whether bean definition overriding is allowed
* @param initializers the initializers
* @param environmentProperties the environment properties
* @param systemProperties the system properties
Expand All @@ -139,7 +144,7 @@ protected AbstractApplicationContextRunner(Supplier<C> contextFactory) {
* @param beanRegistrations the bean registrations
* @param configurations the configuration
*/
protected AbstractApplicationContextRunner(Supplier<C> contextFactory,
protected AbstractApplicationContextRunner(Supplier<C> contextFactory, boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super C>> initializers, TestPropertyValues environmentProperties,
TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent,
List<BeanRegistration<?>> beanRegistrations, List<Configurations> configurations) {
Expand All @@ -149,6 +154,7 @@ protected AbstractApplicationContextRunner(Supplier<C> contextFactory,
Assert.notNull(configurations, "Configurations must not be null");
Assert.notNull(initializers, "Initializers must not be null");
this.contextFactory = contextFactory;
this.allowBeanDefinitionOverriding = allowBeanDefinitionOverriding;
this.initializers = Collections.unmodifiableList(initializers);
this.environmentProperties = environmentProperties;
this.systemProperties = systemProperties;
Expand All @@ -159,15 +165,30 @@ protected AbstractApplicationContextRunner(Supplier<C> contextFactory,
}

/**
* Add a {@link ApplicationContextInitializer} to be called when the context is
* created.
* Specify if bean definition overriding, by registering a definition with the same
* name as an existing definition, should be allowed.
* @param allowBeanDefinitionOverriding if bean overriding is allowed
* @return a new instance with the updated bean definition overriding policy
* @since 2.3.0
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding(boolean)
*/
public SELF withAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding) {
return newInstance(this.contextFactory, allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties, this.classLoader, this.parent,
this.beanRegistrations, this.configurations);
}

/**
* Add a {@link ApplicationContextInitializer} to be
* calWebMvcEndpointChildContextConfigurationTestsled when the context is created.
* @param initializer the initializer to add
* @return a new instance with the updated initializers
*/
public SELF withInitializer(ApplicationContextInitializer<? super C> initializer) {
Assert.notNull(initializer, "Initializer must not be null");
return newInstance(this.contextFactory, add(this.initializers, initializer), this.environmentProperties,
this.systemProperties, this.classLoader, this.parent, this.beanRegistrations, this.configurations);
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, add(this.initializers, initializer),
this.environmentProperties, this.systemProperties, this.classLoader, this.parent,
this.beanRegistrations, this.configurations);
}

/**
Expand All @@ -181,8 +202,9 @@ public SELF withInitializer(ApplicationContextInitializer<? super C> initializer
* @see #withSystemProperties(String...)
*/
public SELF withPropertyValues(String... pairs) {
return newInstance(this.contextFactory, this.initializers, this.environmentProperties.and(pairs),
this.systemProperties, this.classLoader, this.parent, this.beanRegistrations, this.configurations);
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties.and(pairs), this.systemProperties, this.classLoader, this.parent,
this.beanRegistrations, this.configurations);
}

/**
Expand All @@ -196,9 +218,9 @@ public SELF withPropertyValues(String... pairs) {
* @see #withSystemProperties(String...)
*/
public SELF withSystemProperties(String... pairs) {
return newInstance(this.contextFactory, this.initializers, this.environmentProperties,
this.systemProperties.and(pairs), this.classLoader, this.parent, this.beanRegistrations,
this.configurations);
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties.and(pairs), this.classLoader, this.parent,
this.beanRegistrations, this.configurations);
}

/**
Expand All @@ -209,8 +231,9 @@ public SELF withSystemProperties(String... pairs) {
* @see FilteredClassLoader
*/
public SELF withClassLoader(ClassLoader classLoader) {
return newInstance(this.contextFactory, this.initializers, this.environmentProperties, this.systemProperties,
classLoader, this.parent, this.beanRegistrations, this.configurations);
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties, classLoader, this.parent, this.beanRegistrations,
this.configurations);
}

/**
Expand All @@ -220,8 +243,9 @@ public SELF withClassLoader(ClassLoader classLoader) {
* @return a new instance with the updated parent
*/
public SELF withParent(ApplicationContext parent) {
return newInstance(this.contextFactory, this.initializers, this.environmentProperties, this.systemProperties,
this.classLoader, parent, this.beanRegistrations, this.configurations);
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties, this.classLoader, parent, this.beanRegistrations,
this.configurations);
}

/**
Expand Down Expand Up @@ -256,8 +280,8 @@ public <T> SELF withBean(Class<T> type, Object... constructorArgs) {
* @return a new instance with the updated bean
*/
public <T> SELF withBean(String name, Class<T> type, Object... constructorArgs) {
return newInstance(this.contextFactory, this.initializers, this.environmentProperties, this.systemProperties,
this.classLoader, this.parent,
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties, this.classLoader, this.parent,
add(this.beanRegistrations, new BeanRegistration<>(name, type, constructorArgs)), this.configurations);
}

Expand Down Expand Up @@ -296,8 +320,8 @@ public <T> SELF withBean(Class<T> type, Supplier<T> supplier, BeanDefinitionCust
*/
public <T> SELF withBean(String name, Class<T> type, Supplier<T> supplier,
BeanDefinitionCustomizer... customizers) {
return newInstance(this.contextFactory, this.initializers, this.environmentProperties, this.systemProperties,
this.classLoader, this.parent,
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties, this.classLoader, this.parent,
add(this.beanRegistrations, new BeanRegistration<>(name, type, supplier, customizers)),
this.configurations);
}
Expand All @@ -319,8 +343,9 @@ public SELF withUserConfiguration(Class<?>... configurationClasses) {
*/
public SELF withConfiguration(Configurations configurations) {
Assert.notNull(configurations, "Configurations must not be null");
return newInstance(this.contextFactory, this.initializers, this.environmentProperties, this.systemProperties,
this.classLoader, this.parent, this.beanRegistrations, add(this.configurations, configurations));
return newInstance(this.contextFactory, this.allowBeanDefinitionOverriding, this.initializers,
this.environmentProperties, this.systemProperties, this.classLoader, this.parent,
this.beanRegistrations, add(this.configurations, configurations));
}

/**
Expand All @@ -339,7 +364,7 @@ private <T> List<T> add(List<T> list, T element) {
return result;
}

protected abstract SELF newInstance(Supplier<C> contextFactory,
protected abstract SELF newInstance(Supplier<C> contextFactory, boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super C>> initializers, TestPropertyValues environmentProperties,
TestPropertyValues systemProperties, ClassLoader classLoader, ApplicationContext parent,
List<BeanRegistration<?>> beanRegistrations, List<Configurations> configurations);
Expand Down Expand Up @@ -388,6 +413,11 @@ private A createAssertableContext() {

private C createAndLoadContext() {
C context = this.contextFactory.get();
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
try {
configureContext(context);
return context;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand Down Expand Up @@ -59,22 +59,24 @@ public ApplicationContextRunner(Supplier<ConfigurableApplicationContext> context
}

private ApplicationContextRunner(Supplier<ConfigurableApplicationContext> contextFactory,
boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super ConfigurableApplicationContext>> initializers,
TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader,
ApplicationContext parent, List<BeanRegistration<?>> beanRegistrations,
List<Configurations> configurations) {
super(contextFactory, initializers, environmentProperties, systemProperties, classLoader, parent,
beanRegistrations, configurations);
super(contextFactory, allowBeanDefinitionOverriding, initializers, environmentProperties, systemProperties,
classLoader, parent, beanRegistrations, configurations);
}

@Override
protected ApplicationContextRunner newInstance(Supplier<ConfigurableApplicationContext> contextFactory,
boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super ConfigurableApplicationContext>> initializers,
TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader,
ApplicationContext parent, List<BeanRegistration<?>> beanRegistrations,
List<Configurations> configurations) {
return new ApplicationContextRunner(contextFactory, initializers, environmentProperties, systemProperties,
classLoader, parent, beanRegistrations, configurations);
return new ApplicationContextRunner(contextFactory, allowBeanDefinitionOverriding, initializers,
environmentProperties, systemProperties, classLoader, parent, beanRegistrations, configurations);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand Down Expand Up @@ -59,23 +59,24 @@ public ReactiveWebApplicationContextRunner(Supplier<ConfigurableReactiveWebAppli
}

private ReactiveWebApplicationContextRunner(Supplier<ConfigurableReactiveWebApplicationContext> contextFactory,
boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super ConfigurableReactiveWebApplicationContext>> initializers,
TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader,
ApplicationContext parent, List<BeanRegistration<?>> beanRegistrations,
List<Configurations> configurations) {
super(contextFactory, initializers, environmentProperties, systemProperties, classLoader, parent,
beanRegistrations, configurations);
super(contextFactory, allowBeanDefinitionOverriding, initializers, environmentProperties, systemProperties,
classLoader, parent, beanRegistrations, configurations);
}

@Override
protected ReactiveWebApplicationContextRunner newInstance(
Supplier<ConfigurableReactiveWebApplicationContext> contextFactory,
Supplier<ConfigurableReactiveWebApplicationContext> contextFactory, boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super ConfigurableReactiveWebApplicationContext>> initializers,
TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader,
ApplicationContext parent, List<BeanRegistration<?>> beanRegistrations,
List<Configurations> configurations) {
return new ReactiveWebApplicationContextRunner(contextFactory, initializers, environmentProperties,
systemProperties, classLoader, parent, beanRegistrations, configurations);
return new ReactiveWebApplicationContextRunner(contextFactory, allowBeanDefinitionOverriding, initializers,
environmentProperties, systemProperties, classLoader, parent, beanRegistrations, configurations);
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2020 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.
Expand Down Expand Up @@ -63,22 +63,24 @@ public WebApplicationContextRunner(Supplier<ConfigurableWebApplicationContext> c
}

private WebApplicationContextRunner(Supplier<ConfigurableWebApplicationContext> contextFactory,
boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super ConfigurableWebApplicationContext>> initializers,
TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader,
ApplicationContext parent, List<BeanRegistration<?>> beanRegistrations,
List<Configurations> configurations) {
super(contextFactory, initializers, environmentProperties, systemProperties, classLoader, parent,
beanRegistrations, configurations);
super(contextFactory, allowBeanDefinitionOverriding, initializers, environmentProperties, systemProperties,
classLoader, parent, beanRegistrations, configurations);
}

@Override
protected WebApplicationContextRunner newInstance(Supplier<ConfigurableWebApplicationContext> contextFactory,
boolean allowBeanDefinitionOverriding,
List<ApplicationContextInitializer<? super ConfigurableWebApplicationContext>> initializers,
TestPropertyValues environmentProperties, TestPropertyValues systemProperties, ClassLoader classLoader,
ApplicationContext parent, List<BeanRegistration<?>> beanRegistrations,
List<Configurations> configurations) {
return new WebApplicationContextRunner(contextFactory, initializers, environmentProperties, systemProperties,
classLoader, parent, beanRegistrations, configurations);
return new WebApplicationContextRunner(contextFactory, allowBeanDefinitionOverriding, initializers,
environmentProperties, systemProperties, classLoader, parent, beanRegistrations, configurations);
}

/**
Expand Down
Loading

0 comments on commit eb852f1

Please sign in to comment.