Skip to content

Commit 1c7bff7

Browse files
committed
Merge branch '2.6.x' into 2.7.x
Closes gh-32826
2 parents 7bd9754 + 463a614 commit 1c7bff7

12 files changed

+177
-67
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationContextFactory.java

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020

2121
import org.springframework.beans.BeanUtils;
2222
import org.springframework.context.ConfigurableApplicationContext;
23-
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
24-
import org.springframework.core.io.support.SpringFactoriesLoader;
23+
import org.springframework.core.env.ConfigurableEnvironment;
24+
import org.springframework.core.env.Environment;
2525

2626
/**
2727
* Strategy interface for creating the {@link ConfigurableApplicationContext} used by a
@@ -40,22 +40,32 @@ public interface ApplicationContextFactory {
4040
* A default {@link ApplicationContextFactory} implementation that will create an
4141
* appropriate context for the {@link WebApplicationType}.
4242
*/
43-
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
44-
try {
45-
for (ApplicationContextFactory candidate : SpringFactoriesLoader
46-
.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) {
47-
ConfigurableApplicationContext context = candidate.create(webApplicationType);
48-
if (context != null) {
49-
return context;
50-
}
51-
}
52-
return new AnnotationConfigApplicationContext();
53-
}
54-
catch (Exception ex) {
55-
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
56-
+ "you may need a custom ApplicationContextFactory", ex);
57-
}
58-
};
43+
ApplicationContextFactory DEFAULT = new DefaultApplicationContextFactory();
44+
45+
/**
46+
* Return the {@link Environment} type expected to be set on the
47+
* {@link #create(WebApplicationType) created} application context. The result of this
48+
* method can be used to convert an existing environment instance to the correct type.
49+
* @param webApplicationType the web application type
50+
* @return the expected application context type or {@code null} to use the default
51+
* @since 2.6.14
52+
*/
53+
default Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
54+
return null;
55+
}
56+
57+
/**
58+
* Create a new {@link Environment} to be set on the
59+
* {@link #create(WebApplicationType) created} application context. The result of this
60+
* method must match the type returned by
61+
* {@link #getEnvironmentType(WebApplicationType)}.
62+
* @param webApplicationType the web application type
63+
* @return an environment instance or {@code null} to use the default
64+
* @since 2.6.14
65+
*/
66+
default ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
67+
return null;
68+
}
5969

6070
/**
6171
* Creates the {@link ConfigurableApplicationContext application context} for a
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/*
2+
* Copyright 2012-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot;
18+
19+
import java.util.function.BiFunction;
20+
import java.util.function.Supplier;
21+
22+
import org.springframework.context.ConfigurableApplicationContext;
23+
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
24+
import org.springframework.core.env.ConfigurableEnvironment;
25+
import org.springframework.core.io.support.SpringFactoriesLoader;
26+
27+
/**
28+
* Default {@link ApplicationContextFactory} implementation that will create an
29+
* appropriate context for the {@link WebApplicationType}.
30+
*
31+
* @author Phillip Webb
32+
*/
33+
class DefaultApplicationContextFactory implements ApplicationContextFactory {
34+
35+
@Override
36+
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
37+
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::getEnvironmentType, null);
38+
}
39+
40+
@Override
41+
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
42+
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::createEnvironment, null);
43+
}
44+
45+
@Override
46+
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
47+
try {
48+
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
49+
AnnotationConfigApplicationContext::new);
50+
}
51+
catch (Exception ex) {
52+
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
53+
+ "you may need a custom ApplicationContextFactory", ex);
54+
}
55+
}
56+
57+
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
58+
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
59+
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
60+
getClass().getClassLoader())) {
61+
T result = action.apply(candidate, webApplicationType);
62+
if (result != null) {
63+
return result;
64+
}
65+
}
66+
return (defaultResult != null) ? defaultResult.get() : null;
67+
}
68+
69+
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/EnvironmentConverter.java

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.boot;
1818

19+
import java.lang.reflect.Constructor;
1920
import java.util.Collections;
2021
import java.util.HashSet;
2122
import java.util.Set;
@@ -26,6 +27,7 @@
2627
import org.springframework.core.env.PropertySource;
2728
import org.springframework.core.env.StandardEnvironment;
2829
import org.springframework.util.ClassUtils;
30+
import org.springframework.util.ReflectionUtils;
2931
import org.springframework.web.context.support.StandardServletEnvironment;
3032

3133
/**
@@ -68,33 +70,35 @@ final class EnvironmentConverter {
6870
* @param type the type to convert the Environment to
6971
* @return the converted Environment
7072
*/
71-
StandardEnvironment convertEnvironmentIfNecessary(ConfigurableEnvironment environment,
72-
Class<? extends StandardEnvironment> type) {
73+
ConfigurableEnvironment convertEnvironmentIfNecessary(ConfigurableEnvironment environment,
74+
Class<? extends ConfigurableEnvironment> type) {
7375
if (type.equals(environment.getClass())) {
74-
return (StandardEnvironment) environment;
76+
return environment;
7577
}
7678
return convertEnvironment(environment, type);
7779
}
7880

79-
private StandardEnvironment convertEnvironment(ConfigurableEnvironment environment,
80-
Class<? extends StandardEnvironment> type) {
81-
StandardEnvironment result = createEnvironment(type);
81+
private ConfigurableEnvironment convertEnvironment(ConfigurableEnvironment environment,
82+
Class<? extends ConfigurableEnvironment> type) {
83+
ConfigurableEnvironment result = createEnvironment(type);
8284
result.setActiveProfiles(environment.getActiveProfiles());
8385
result.setConversionService(environment.getConversionService());
8486
copyPropertySources(environment, result);
8587
return result;
8688
}
8789

88-
private StandardEnvironment createEnvironment(Class<? extends StandardEnvironment> type) {
90+
private ConfigurableEnvironment createEnvironment(Class<? extends ConfigurableEnvironment> type) {
8991
try {
90-
return type.getDeclaredConstructor().newInstance();
92+
Constructor<? extends ConfigurableEnvironment> constructor = type.getDeclaredConstructor();
93+
ReflectionUtils.makeAccessible(constructor);
94+
return constructor.newInstance();
9195
}
9296
catch (Exception ex) {
93-
return new StandardEnvironment();
97+
return new ApplicationEnvironment();
9498
}
9599
}
96100

97-
private void copyPropertySources(ConfigurableEnvironment source, StandardEnvironment target) {
101+
private void copyPropertySources(ConfigurableEnvironment source, ConfigurableEnvironment target) {
98102
removePropertySources(target.getPropertySources(), isServletEnvironment(target.getClass(), this.classLoader));
99103
for (PropertySource<?> propertySource : source.getPropertySources()) {
100104
if (!SERVLET_ENVIRONMENT_SOURCE_NAMES.contains(propertySource.getName())) {

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
import org.springframework.core.env.MutablePropertySources;
7575
import org.springframework.core.env.PropertySource;
7676
import org.springframework.core.env.SimpleCommandLinePropertySource;
77-
import org.springframework.core.env.StandardEnvironment;
7877
import org.springframework.core.io.DefaultResourceLoader;
7978
import org.springframework.core.io.ResourceLoader;
8079
import org.springframework.core.io.support.SpringFactoriesLoader;
@@ -354,15 +353,16 @@ private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners
354353
return environment;
355354
}
356355

357-
private Class<? extends StandardEnvironment> deduceEnvironmentClass() {
358-
switch (this.webApplicationType) {
359-
case SERVLET:
360-
return ApplicationServletEnvironment.class;
361-
case REACTIVE:
362-
return ApplicationReactiveWebEnvironment.class;
363-
default:
364-
return ApplicationEnvironment.class;
356+
private Class<? extends ConfigurableEnvironment> deduceEnvironmentClass() {
357+
Class<? extends ConfigurableEnvironment> environmentType = this.applicationContextFactory
358+
.getEnvironmentType(this.webApplicationType);
359+
if (environmentType == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
360+
environmentType = ApplicationContextFactory.DEFAULT.getEnvironmentType(this.webApplicationType);
365361
}
362+
if (environmentType == null) {
363+
return ApplicationEnvironment.class;
364+
}
365+
return environmentType;
366366
}
367367

368368
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
@@ -456,14 +456,11 @@ private ConfigurableEnvironment getOrCreateEnvironment() {
456456
if (this.environment != null) {
457457
return this.environment;
458458
}
459-
switch (this.webApplicationType) {
460-
case SERVLET:
461-
return new ApplicationServletEnvironment();
462-
case REACTIVE:
463-
return new ApplicationReactiveWebEnvironment();
464-
default:
465-
return new ApplicationEnvironment();
459+
ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType);
460+
if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
461+
environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType);
466462
}
463+
return (environment != null) ? environment : new ApplicationEnvironment();
467464
}
468465

469466
/**

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/AnnotationConfigReactiveWebServerApplicationContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,16 @@ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactor
218218
*/
219219
static class Factory implements ApplicationContextFactory {
220220

221+
@Override
222+
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
223+
return (webApplicationType != WebApplicationType.REACTIVE) ? null : ApplicationReactiveWebEnvironment.class;
224+
}
225+
226+
@Override
227+
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
228+
return (webApplicationType != WebApplicationType.REACTIVE) ? null : new ApplicationReactiveWebEnvironment();
229+
}
230+
221231
@Override
222232
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
223233
return (webApplicationType != WebApplicationType.REACTIVE) ? null

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationReactiveWebEnvironment.java renamed to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/reactive/context/ApplicationReactiveWebEnvironment.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,10 +14,10 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.boot;
17+
package org.springframework.boot.web.reactive.context;
1818

19+
import org.springframework.boot.SpringApplication;
1920
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
20-
import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment;
2121
import org.springframework.core.env.ConfigurablePropertyResolver;
2222
import org.springframework.core.env.MutablePropertySources;
2323

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/AnnotationConfigServletWebServerApplicationContext.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,16 @@ protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactor
215215
*/
216216
static class Factory implements ApplicationContextFactory {
217217

218+
@Override
219+
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
220+
return (webApplicationType != WebApplicationType.SERVLET) ? null : ApplicationServletEnvironment.class;
221+
}
222+
223+
@Override
224+
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
225+
return (webApplicationType != WebApplicationType.SERVLET) ? null : new ApplicationServletEnvironment();
226+
}
227+
218228
@Override
219229
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
220230
return (webApplicationType != WebApplicationType.SERVLET) ? null

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ApplicationServletEnvironment.java renamed to spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/context/ApplicationServletEnvironment.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -14,8 +14,9 @@
1414
* limitations under the License.
1515
*/
1616

17-
package org.springframework.boot;
17+
package org.springframework.boot.web.servlet.context;
1818

19+
import org.springframework.boot.SpringApplication;
1920
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
2021
import org.springframework.core.env.ConfigurablePropertyResolver;
2122
import org.springframework.core.env.MutablePropertySources;

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/EnvironmentConverterTests.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.springframework.core.convert.support.ConfigurableConversionService;
2525
import org.springframework.core.env.AbstractEnvironment;
26+
import org.springframework.core.env.ConfigurableEnvironment;
2627
import org.springframework.core.env.PropertySource;
2728
import org.springframework.core.env.StandardEnvironment;
2829
import org.springframework.mock.env.MockEnvironment;
@@ -46,7 +47,7 @@ class EnvironmentConverterTests {
4647
void convertedEnvironmentHasSameActiveProfiles() {
4748
AbstractEnvironment originalEnvironment = new MockEnvironment();
4849
originalEnvironment.setActiveProfiles("activeProfile1", "activeProfile2");
49-
StandardEnvironment convertedEnvironment = this.environmentConverter
50+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
5051
.convertEnvironmentIfNecessary(originalEnvironment, StandardEnvironment.class);
5152
assertThat(convertedEnvironment.getActiveProfiles()).containsExactly("activeProfile1", "activeProfile2");
5253
}
@@ -56,31 +57,31 @@ void convertedEnvironmentHasSameConversionService() {
5657
AbstractEnvironment originalEnvironment = new MockEnvironment();
5758
ConfigurableConversionService conversionService = mock(ConfigurableConversionService.class);
5859
originalEnvironment.setConversionService(conversionService);
59-
StandardEnvironment convertedEnvironment = this.environmentConverter
60+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
6061
.convertEnvironmentIfNecessary(originalEnvironment, StandardEnvironment.class);
6162
assertThat(convertedEnvironment.getConversionService()).isEqualTo(conversionService);
6263
}
6364

6465
@Test
6566
void envClassSameShouldReturnEnvironmentUnconverted() {
6667
StandardEnvironment standardEnvironment = new StandardEnvironment();
67-
StandardEnvironment convertedEnvironment = this.environmentConverter
68+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
6869
.convertEnvironmentIfNecessary(standardEnvironment, StandardEnvironment.class);
6970
assertThat(convertedEnvironment).isSameAs(standardEnvironment);
7071
}
7172

7273
@Test
7374
void standardServletEnvironmentIsConverted() {
7475
StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment();
75-
StandardEnvironment convertedEnvironment = this.environmentConverter
76+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
7677
.convertEnvironmentIfNecessary(standardServletEnvironment, StandardEnvironment.class);
7778
assertThat(convertedEnvironment).isNotSameAs(standardServletEnvironment);
7879
}
7980

8081
@Test
8182
void servletPropertySourcesAreNotCopiedOverIfNotWebEnvironment() {
8283
StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment();
83-
StandardEnvironment convertedEnvironment = this.environmentConverter
84+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
8485
.convertEnvironmentIfNecessary(standardServletEnvironment, StandardEnvironment.class);
8586
assertThat(convertedEnvironment).isNotSameAs(standardServletEnvironment);
8687
Set<String> names = new HashSet<>();
@@ -95,15 +96,15 @@ void servletPropertySourcesAreNotCopiedOverIfNotWebEnvironment() {
9596
@Test
9697
void envClassSameShouldReturnEnvironmentUnconvertedEvenForWeb() {
9798
StandardServletEnvironment standardServletEnvironment = new StandardServletEnvironment();
98-
StandardEnvironment convertedEnvironment = this.environmentConverter
99+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
99100
.convertEnvironmentIfNecessary(standardServletEnvironment, StandardServletEnvironment.class);
100101
assertThat(convertedEnvironment).isSameAs(standardServletEnvironment);
101102
}
102103

103104
@Test
104105
void servletPropertySourcesArePresentWhenTypeToConvertIsWeb() {
105106
StandardEnvironment standardEnvironment = new StandardEnvironment();
106-
StandardEnvironment convertedEnvironment = this.environmentConverter
107+
ConfigurableEnvironment convertedEnvironment = this.environmentConverter
107108
.convertEnvironmentIfNecessary(standardEnvironment, StandardServletEnvironment.class);
108109
assertThat(convertedEnvironment).isNotSameAs(standardEnvironment);
109110
Set<String> names = new HashSet<>();

0 commit comments

Comments
 (0)