Fix package tangle between SpringApplication and Environment types
Update `SpringApplication` so that it no longer directly decides the type of `Environment` that should be created. Closes gh-32825
This commit is contained in:
parent
81beb2e0c6
commit
463a614d27
|
|
@ -20,8 +20,8 @@ import java.util.function.Supplier;
|
|||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
/**
|
||||
* Strategy interface for creating the {@link ConfigurableApplicationContext} used by a
|
||||
|
|
@ -40,22 +40,32 @@ public interface ApplicationContextFactory {
|
|||
* A default {@link ApplicationContextFactory} implementation that will create an
|
||||
* appropriate context for the {@link WebApplicationType}.
|
||||
*/
|
||||
ApplicationContextFactory DEFAULT = (webApplicationType) -> {
|
||||
try {
|
||||
for (ApplicationContextFactory candidate : SpringFactoriesLoader
|
||||
.loadFactories(ApplicationContextFactory.class, ApplicationContextFactory.class.getClassLoader())) {
|
||||
ConfigurableApplicationContext context = candidate.create(webApplicationType);
|
||||
if (context != null) {
|
||||
return context;
|
||||
ApplicationContextFactory DEFAULT = new DefaultApplicationContextFactory();
|
||||
|
||||
/**
|
||||
* Return the {@link Environment} type expected to be set on the
|
||||
* {@link #create(WebApplicationType) created} application context. The result of this
|
||||
* method can be used to convert an existing environment instance to the correct type.
|
||||
* @param webApplicationType the web application type
|
||||
* @return the expected application context type or {@code null} to use the default
|
||||
* @since 2.6.14
|
||||
*/
|
||||
default Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link Environment} to be set on the
|
||||
* {@link #create(WebApplicationType) created} application context. The result of this
|
||||
* method must match the type returned by
|
||||
* {@link #getEnvironmentType(WebApplicationType)}.
|
||||
* @param webApplicationType the web application type
|
||||
* @return an environment instance or {@code null} to use the default
|
||||
* @since 2.6.14
|
||||
*/
|
||||
default ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
|
||||
return null;
|
||||
}
|
||||
return new AnnotationConfigApplicationContext();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
|
||||
+ "you may need a custom ApplicationContextFactory", ex);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates the {@link ConfigurableApplicationContext application context} for a
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright 2012-2022 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.io.support.SpringFactoriesLoader;
|
||||
|
||||
/**
|
||||
* Default {@link ApplicationContextFactory} implementation that will create an
|
||||
* appropriate context for the {@link WebApplicationType}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class DefaultApplicationContextFactory implements ApplicationContextFactory {
|
||||
|
||||
@Override
|
||||
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
|
||||
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::getEnvironmentType, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
|
||||
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::createEnvironment, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
|
||||
try {
|
||||
return getFromSpringFactories(webApplicationType, ApplicationContextFactory::create,
|
||||
AnnotationConfigApplicationContext::new);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
|
||||
+ "you may need a custom ApplicationContextFactory", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private <T> T getFromSpringFactories(WebApplicationType webApplicationType,
|
||||
BiFunction<ApplicationContextFactory, WebApplicationType, T> action, Supplier<T> defaultResult) {
|
||||
for (ApplicationContextFactory candidate : SpringFactoriesLoader.loadFactories(ApplicationContextFactory.class,
|
||||
getClass().getClassLoader())) {
|
||||
T result = action.apply(candidate, webApplicationType);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return (defaultResult != null) ? defaultResult.get() : null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.boot;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
|
@ -26,6 +27,7 @@ import org.springframework.core.env.MutablePropertySources;
|
|||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.web.context.support.StandardServletEnvironment;
|
||||
|
||||
/**
|
||||
|
|
@ -87,10 +89,12 @@ final class EnvironmentConverter {
|
|||
|
||||
private StandardEnvironment createEnvironment(Class<? extends StandardEnvironment> type) {
|
||||
try {
|
||||
return type.getDeclaredConstructor().newInstance();
|
||||
Constructor<? extends StandardEnvironment> constructor = type.getDeclaredConstructor();
|
||||
ReflectionUtils.makeAccessible(constructor);
|
||||
return constructor.newInstance();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return new StandardEnvironment();
|
||||
return new ApplicationEnvironment();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -366,15 +366,18 @@ public class SpringApplication {
|
|||
deduceEnvironmentClass());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Class<? extends StandardEnvironment> deduceEnvironmentClass() {
|
||||
switch (this.webApplicationType) {
|
||||
case SERVLET:
|
||||
return ApplicationServletEnvironment.class;
|
||||
case REACTIVE:
|
||||
return ApplicationReactiveWebEnvironment.class;
|
||||
default:
|
||||
Class<? extends ConfigurableEnvironment> environmentType = this.applicationContextFactory
|
||||
.getEnvironmentType(this.webApplicationType);
|
||||
if (environmentType == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
|
||||
environmentType = ApplicationContextFactory.DEFAULT.getEnvironmentType(this.webApplicationType);
|
||||
}
|
||||
if (environmentType == null) {
|
||||
return ApplicationEnvironment.class;
|
||||
}
|
||||
Assert.isAssignable(StandardEnvironment.class, environmentType);
|
||||
return (Class<? extends StandardEnvironment>) environmentType;
|
||||
}
|
||||
|
||||
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context,
|
||||
|
|
@ -468,14 +471,11 @@ public class SpringApplication {
|
|||
if (this.environment != null) {
|
||||
return this.environment;
|
||||
}
|
||||
switch (this.webApplicationType) {
|
||||
case SERVLET:
|
||||
return new ApplicationServletEnvironment();
|
||||
case REACTIVE:
|
||||
return new ApplicationReactiveWebEnvironment();
|
||||
default:
|
||||
return new ApplicationEnvironment();
|
||||
ConfigurableEnvironment environment = this.applicationContextFactory.createEnvironment(this.webApplicationType);
|
||||
if (environment == null && this.applicationContextFactory != ApplicationContextFactory.DEFAULT) {
|
||||
environment = ApplicationContextFactory.DEFAULT.createEnvironment(this.webApplicationType);
|
||||
}
|
||||
return (environment != null) ? environment : new ApplicationEnvironment();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -218,6 +218,16 @@ public class AnnotationConfigReactiveWebServerApplicationContext extends Reactiv
|
|||
*/
|
||||
static class Factory implements ApplicationContextFactory {
|
||||
|
||||
@Override
|
||||
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
|
||||
return (webApplicationType != WebApplicationType.REACTIVE) ? null : ApplicationReactiveWebEnvironment.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
|
||||
return (webApplicationType != WebApplicationType.REACTIVE) ? null : new ApplicationReactiveWebEnvironment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
|
||||
return (webApplicationType != WebApplicationType.REACTIVE) ? null
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
|
@ -14,10 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot;
|
||||
package org.springframework.boot.web.reactive.context;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment;
|
||||
import org.springframework.core.env.ConfigurablePropertyResolver;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
|
||||
|
|
@ -215,6 +215,16 @@ public class AnnotationConfigServletWebServerApplicationContext extends ServletW
|
|||
*/
|
||||
static class Factory implements ApplicationContextFactory {
|
||||
|
||||
@Override
|
||||
public Class<? extends ConfigurableEnvironment> getEnvironmentType(WebApplicationType webApplicationType) {
|
||||
return (webApplicationType != WebApplicationType.SERVLET) ? null : ApplicationServletEnvironment.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableEnvironment createEnvironment(WebApplicationType webApplicationType) {
|
||||
return (webApplicationType != WebApplicationType.SERVLET) ? null : new ApplicationServletEnvironment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ConfigurableApplicationContext create(WebApplicationType webApplicationType) {
|
||||
return (webApplicationType != WebApplicationType.SERVLET) ? null
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
|
@ -14,8 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot;
|
||||
package org.springframework.boot.web.servlet.context;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
|
||||
import org.springframework.core.env.ConfigurablePropertyResolver;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
|
|
@ -74,6 +74,7 @@ import org.springframework.boot.web.embedded.netty.NettyReactiveWebServerFactory
|
|||
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
|
||||
import org.springframework.boot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext;
|
||||
import org.springframework.boot.web.reactive.context.ReactiveWebApplicationContext;
|
||||
import org.springframework.boot.web.reactive.context.StandardReactiveWebEnvironment;
|
||||
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
|
|
@ -472,7 +473,8 @@ class SpringApplicationTests {
|
|||
SpringApplication application = new SpringApplication(ExampleWebConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.SERVLET);
|
||||
this.context = application.run();
|
||||
assertThat(this.context.getEnvironment()).isInstanceOf(ApplicationServletEnvironment.class);
|
||||
assertThat(this.context.getEnvironment()).isInstanceOf(StandardServletEnvironment.class);
|
||||
assertThat(this.context.getEnvironment().getClass().getName()).endsWith("ApplicationServletEnvironment");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -480,7 +482,8 @@ class SpringApplicationTests {
|
|||
SpringApplication application = new SpringApplication(ExampleReactiveWebConfig.class);
|
||||
application.setWebApplicationType(WebApplicationType.REACTIVE);
|
||||
this.context = application.run();
|
||||
assertThat(this.context.getEnvironment()).isInstanceOf(ApplicationReactiveWebEnvironment.class);
|
||||
assertThat(this.context.getEnvironment()).isInstanceOf(StandardReactiveWebEnvironment.class);
|
||||
assertThat(this.context.getEnvironment().getClass().getName()).endsWith("ApplicationReactiveWebEnvironment");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1055,7 +1058,7 @@ class SpringApplicationTests {
|
|||
void webApplicationSwitchedOffInListener() {
|
||||
TestSpringApplication application = new TestSpringApplication(ExampleConfig.class);
|
||||
application.addListeners((ApplicationListener<ApplicationEnvironmentPreparedEvent>) (event) -> {
|
||||
assertThat(event.getEnvironment()).isInstanceOf(ApplicationServletEnvironment.class);
|
||||
assertThat(event.getEnvironment().getClass().getName()).endsWith("ApplicationServletEnvironment");
|
||||
TestPropertySourceUtils.addInlinedPropertiesToEnvironment(event.getEnvironment(), "foo=bar");
|
||||
event.getSpringApplication().setWebApplicationType(WebApplicationType.NONE);
|
||||
});
|
||||
|
|
@ -1081,7 +1084,8 @@ class SpringApplicationTests {
|
|||
ConfigurableApplicationContext context = new SpringApplication(ExampleWebConfig.class)
|
||||
.run("--spring.main.web-application-type=servlet");
|
||||
assertThat(context).isInstanceOf(WebApplicationContext.class);
|
||||
assertThat(context.getEnvironment()).isInstanceOf(ApplicationServletEnvironment.class);
|
||||
assertThat(context.getEnvironment()).isInstanceOf(StandardServletEnvironment.class);
|
||||
assertThat(context.getEnvironment().getClass().getName()).endsWith("ApplicationServletEnvironment");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1089,7 +1093,8 @@ class SpringApplicationTests {
|
|||
ConfigurableApplicationContext context = new SpringApplication(ExampleReactiveWebConfig.class)
|
||||
.run("--spring.main.web-application-type=reactive");
|
||||
assertThat(context).isInstanceOf(ReactiveWebApplicationContext.class);
|
||||
assertThat(context.getEnvironment()).isInstanceOf(ApplicationReactiveWebEnvironment.class);
|
||||
assertThat(context.getEnvironment()).isInstanceOf(StandardReactiveWebEnvironment.class);
|
||||
assertThat(context.getEnvironment().getClass().getName()).endsWith("ApplicationReactiveWebEnvironment");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -1097,7 +1102,8 @@ class SpringApplicationTests {
|
|||
ConfigurableApplicationContext context = new SpringApplication(ExampleReactiveWebConfig.class)
|
||||
.run("--spring.profiles.active=withwebapplicationtype");
|
||||
assertThat(context).isInstanceOf(ReactiveWebApplicationContext.class);
|
||||
assertThat(context.getEnvironment()).isInstanceOf(ApplicationReactiveWebEnvironment.class);
|
||||
assertThat(context.getEnvironment()).isInstanceOf(StandardReactiveWebEnvironment.class);
|
||||
assertThat(context.getEnvironment().getClass().getName()).endsWith("ApplicationReactiveWebEnvironment");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
|
@ -14,8 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot;
|
||||
package org.springframework.boot.web.reactive.context;
|
||||
|
||||
import org.springframework.boot.AbstractApplicationEnvironmentTests;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
/**
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
|
|
@ -14,8 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot;
|
||||
package org.springframework.boot.web.servlet.context;
|
||||
|
||||
import org.springframework.boot.AbstractApplicationEnvironmentTests;
|
||||
import org.springframework.core.env.StandardEnvironment;
|
||||
|
||||
/**
|
||||
Loading…
Reference in New Issue