diff --git a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java index 8ab4c4f7c94..fb44272b45b 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -34,11 +34,14 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.BeanUtils; +import org.springframework.beans.CachedIntrospectionResults; import org.springframework.beans.factory.groovy.GroovyBeanDefinitionReader; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; import org.springframework.boot.Banner.Mode; +import org.springframework.boot.bind.PropertiesConfigurationFactory; +import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.diagnostics.FailureAnalyzers; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; @@ -52,6 +55,8 @@ import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.GenericTypeResolver; import org.springframework.core.annotation.AnnotationAwareOrderComparator; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.env.CommandLinePropertySource; import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; @@ -71,6 +76,7 @@ import org.springframework.util.ObjectUtils; import org.springframework.util.ReflectionUtils; import org.springframework.util.StopWatch; import org.springframework.util.StringUtils; +import org.springframework.validation.BindException; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.StandardServletEnvironment; @@ -132,6 +138,12 @@ import org.springframework.web.context.support.StandardServletEnvironment; * resolve to a {@link Resource} that exists it will be considered a {@link Package}. * * + * Configuration properties are also bound to the {@link SpringApplication}. This makes it + * possible to set {@link SpringApplication} properties dynamically, like the sources + * ("spring.main.sources" - a CSV list) the flag to indicate a web environment + * ("spring.main.web_environment=true") or the flag to switch off the banner + * ("spring.main.show_banner=false"). + * * @author Phillip Webb * @author Dave Syer * @author Andy Wilkinson @@ -140,6 +152,7 @@ import org.springframework.web.context.support.StandardServletEnvironment; * @author Jeremy Rickard * @author Craig Burke * @author Michael Simons + * @author Madhura Bhave * @see #run(Object, String[]) * @see #run(Object[], String[]) * @see #SpringApplication(Object...) @@ -306,6 +319,8 @@ public class SpringApplication { args); ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments); + configureIgnoreBeanInfo(environment); + bindToSpringApplication(environment); Banner printedBanner = printBanner(environment); context = createApplicationContext(); analyzers = new FailureAnalyzers(context); @@ -535,6 +550,35 @@ public class SpringApplication { environment.setActiveProfiles(profiles.toArray(new String[profiles.size()])); } + private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) { + if (System.getProperty( + CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) { + RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment, + "spring.beaninfo."); + Boolean ignore = resolver.getProperty("ignore", Boolean.class, Boolean.TRUE); + System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, + ignore.toString()); + } + } + + /** + * Bind the environment to the {@link SpringApplication}. + * @param environment the environment to bind + */ + protected void bindToSpringApplication(ConfigurableEnvironment environment) { + PropertiesConfigurationFactory binder = new PropertiesConfigurationFactory<>(this); + ConversionService conversionService = new DefaultConversionService(); + binder.setTargetName("spring.main"); + binder.setConversionService(conversionService); + binder.setPropertySources(environment.getPropertySources()); + try { + binder.bindPropertiesToTarget(); + } + catch (BindException ex) { + throw new IllegalStateException("Cannot bind to SpringApplication", ex); + } + } + private Banner printBanner(ConfigurableEnvironment environment) { if (this.bannerMode == Banner.Mode.OFF) { return null; diff --git a/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java b/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java index caca89d19d7..c0261fe97ce 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/config/ConfigFileApplicationListener.java @@ -31,14 +31,11 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.springframework.beans.BeansException; -import org.springframework.beans.CachedIntrospectionResults; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.boot.SpringApplication; -import org.springframework.boot.bind.PropertiesConfigurationFactory; import org.springframework.boot.bind.PropertySourcesPropertyValues; import org.springframework.boot.bind.RelaxedDataBinder; -import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationPreparedEvent; import org.springframework.boot.env.EnumerableCompositePropertySource; @@ -51,8 +48,6 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.ConfigurationClassPostProcessor; import org.springframework.core.Ordered; import org.springframework.core.annotation.AnnotationAwareOrderComparator; -import org.springframework.core.convert.ConversionService; -import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.EnumerablePropertySource; import org.springframework.core.env.MutablePropertySources; @@ -65,7 +60,6 @@ import org.springframework.core.io.support.SpringFactoriesLoader; import org.springframework.util.Assert; import org.springframework.util.ResourceUtils; import org.springframework.util.StringUtils; -import org.springframework.validation.BindException; /** * {@link EnvironmentPostProcessor} that configures the context environment by loading @@ -89,11 +83,6 @@ import org.springframework.validation.BindException; * and the 'spring.config.location' property can be used to specify alternative search * locations or specific files. *

- * Configuration properties are also bound to the {@link SpringApplication}. This makes it - * possible to set {@link SpringApplication} properties dynamically, like the sources - * ("spring.main.sources" - a CSV list) the flag to indicate a web environment - * ("spring.main.web_environment=true") or the flag to switch off the banner - * ("spring.main.show_banner=false"). * * @author Dave Syer * @author Phillip Webb @@ -149,8 +138,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, private int order = DEFAULT_ORDER; - private final ConversionService conversionService = new DefaultConversionService(); - @Override public void onApplicationEvent(ApplicationEvent event) { if (event instanceof ApplicationEnvironmentPreparedEvent) { @@ -182,19 +169,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { addPropertySources(environment, application.getResourceLoader()); - configureIgnoreBeanInfo(environment); - bindToSpringApplication(environment, application); - } - - private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) { - if (System.getProperty( - CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) { - RelaxedPropertyResolver resolver = new RelaxedPropertyResolver(environment, - "spring.beaninfo."); - Boolean ignore = resolver.getProperty("ignore", Boolean.class, Boolean.TRUE); - System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, - ignore.toString()); - } } private void onApplicationPreparedEvent(ApplicationEvent event) { @@ -219,26 +193,6 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor, } } - /** - * Bind the environment to the {@link SpringApplication}. - * @param environment the environment to bind - * @param application the application to bind to - */ - protected void bindToSpringApplication(ConfigurableEnvironment environment, - SpringApplication application) { - PropertiesConfigurationFactory binder = new PropertiesConfigurationFactory( - application); - binder.setTargetName("spring.main"); - binder.setConversionService(this.conversionService); - binder.setPropertySources(environment.getPropertySources()); - try { - binder.bindPropertiesToTarget(); - } - catch (BindException ex) { - throw new IllegalStateException("Cannot bind to SpringApplication", ex); - } - } - /** * Add appropriate post-processors to post-configure the property-sources. * @param context the context to configure diff --git a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java index 1cf53cfc3c0..1d00dad2bf5 100644 --- a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -16,6 +16,7 @@ package org.springframework.boot; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -37,6 +38,7 @@ import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.springframework.beans.BeansException; +import org.springframework.beans.CachedIntrospectionResults; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.BeanNameGenerator; import org.springframework.beans.factory.support.DefaultBeanNameGenerator; @@ -75,6 +77,7 @@ import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.test.context.support.TestPropertySourceUtils; +import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import org.springframework.web.context.support.StandardServletEnvironment; @@ -98,6 +101,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; * @author Stephane Nicoll * @author Jeremy Rickard * @author Craig Burke + * @author Madhura Bhave */ public class SpringApplicationTests { @@ -126,6 +130,7 @@ public class SpringApplicationTests { @After public void reinstateHeadlessProperty() { + System.clearProperty("spring.main.banner-mode"); if (this.headlessProperty == null) { System.clearProperty("java.awt.headless"); } @@ -231,6 +236,48 @@ public class SpringApplicationTests { assertThat(this.output.toString()).contains("o.s.boot.SpringApplication"); } + @Test + public void setIgnoreBeanInfoPropertyByDefault() throws Exception { + SpringApplication application = new SpringApplication(ExampleConfig.class); + application.setWebEnvironment(false); + this.context = application.run(); + String property = System + .getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME); + assertThat(property).isEqualTo("true"); + } + + @Test + public void disableIgnoreBeanInfoProperty() throws Exception { + System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, "false"); + SpringApplication application = new SpringApplication(ExampleConfig.class); + application.setWebEnvironment(false); + this.context = application.run(); + String property = System + .getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME); + assertThat(property).isEqualTo("false"); + } + + @Test + public void triggersConfigFileApplicationListenereBeforeBinding() throws Exception { + SpringApplication application = new SpringApplication(ExampleConfig.class); + application.setWebEnvironment(false); + this.context = application.run("--spring.config.name=bindtoapplication"); + Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode"); + field.setAccessible(true); + assertThat((Banner.Mode) field.get(application)).isEqualTo(Banner.Mode.OFF); + } + + @Test + public void bindsSystemPropertyToSpringApplication() throws Exception { + System.setProperty("spring.main.banner-mode", "off"); + SpringApplication application = new SpringApplication(ExampleConfig.class); + application.setWebEnvironment(false); + this.context = application.run(); + Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode"); + field.setAccessible(true); + assertThat((Banner.Mode) field.get(application)).isEqualTo(Banner.Mode.OFF); + } + @Test public void customId() throws Exception { SpringApplication application = new SpringApplication(ExampleConfig.class); diff --git a/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java b/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java index 7ccd17c0522..85c17e7159f 100644 --- a/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/context/config/ConfigFileApplicationListenerTests.java @@ -19,7 +19,6 @@ package org.springframework.boot.context.config; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -39,7 +38,6 @@ import org.junit.rules.ExpectedException; import org.slf4j.LoggerFactory; import org.springframework.beans.CachedIntrospectionResults; -import org.springframework.boot.Banner; import org.springframework.boot.SpringApplication; import org.springframework.boot.context.config.ConfigFileApplicationListener.ConfigurationPropertySources; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; @@ -63,7 +61,6 @@ import org.springframework.core.io.ByteArrayResource; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; import org.springframework.test.context.support.TestPropertySourceUtils; -import org.springframework.util.ReflectionUtils; import org.springframework.util.StringUtils; import static org.assertj.core.api.Assertions.assertThat; @@ -739,26 +736,6 @@ public class ConfigFileApplicationListenerTests { assertThat(property).isEqualTo("baz"); } - @Test - public void bindsToSpringApplication() throws Exception { - // gh-346 - this.initializer.setSearchNames("bindtoapplication"); - this.initializer.postProcessEnvironment(this.environment, this.application); - Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode"); - field.setAccessible(true); - assertThat((Banner.Mode) field.get(this.application)).isEqualTo(Banner.Mode.OFF); - } - - @Test - public void bindsSystemPropertyToSpringApplication() throws Exception { - // gh-951 - System.setProperty("spring.main.banner-mode", "off"); - this.initializer.postProcessEnvironment(this.environment, this.application); - Field field = ReflectionUtils.findField(SpringApplication.class, "bannerMode"); - field.setAccessible(true); - assertThat((Banner.Mode) field.get(this.application)).isEqualTo(Banner.Mode.OFF); - } - @Test public void profileSubDocumentInDifferentProfileSpecificFile() throws Exception { // gh-4132 @@ -770,26 +747,6 @@ public class ConfigFileApplicationListenerTests { assertThat(property).isEqualTo("baz"); } - @Test - public void setIgnoreBeanInfoPropertyByDefault() throws Exception { - this.initializer.setSearchNames("testproperties"); - this.initializer.postProcessEnvironment(this.environment, this.application); - String property = System - .getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME); - assertThat(property).isEqualTo("true"); - } - - @Test - public void disableIgnoreBeanInfoProperty() throws Exception { - this.initializer.setSearchNames("testproperties"); - TestPropertySourceUtils.addInlinedPropertiesToEnvironment(this.environment, - "spring.beaninfo.ignore=false"); - this.initializer.postProcessEnvironment(this.environment, this.application); - String property = System - .getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME); - assertThat(property).isEqualTo("false"); - } - @Test public void addBeforeDefaultProperties() throws Exception { MapPropertySource defaultSource = new MapPropertySource("defaultProperties",