diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java index 0af9497b..8346c63e 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/BootstrapApplicationListener.java @@ -29,7 +29,6 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.builder.ParentContextApplicationContextInitializer; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; -import org.springframework.boot.logging.LoggingSystem; import org.springframework.cloud.bootstrap.encrypt.EnvironmentDecryptApplicationInitializer; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationListener; @@ -85,18 +84,6 @@ public class BootstrapApplicationListener ConfigurableApplicationContext context = bootstrapServiceContext(environment, event.getSpringApplication()); apply(context, event.getSpringApplication(), environment); - shutdownLogging(); - } - - private void shutdownLogging() { - // Clean up the logging system. Logging will go dark until the - // ConfigFileApplicationListener fires, but this is the price we pay for that - // listener being able to adjust the log levels according to what it finds in its - // own configuration. - LoggingSystem loggingSystem = LoggingSystem - .get(ClassUtils.getDefaultClassLoader()); - loggingSystem.cleanUp(); - loggingSystem.beforeInitialize(); } private ConfigurableApplicationContext bootstrapServiceContext( diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/LoggingSystemShutdownListener.java b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/LoggingSystemShutdownListener.java new file mode 100644 index 00000000..684e0098 --- /dev/null +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/bootstrap/LoggingSystemShutdownListener.java @@ -0,0 +1,62 @@ +/* + * Copyright 2013-2015 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 + * + * http://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.cloud.bootstrap; + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.logging.LoggingSystem; +import org.springframework.context.ApplicationListener; +import org.springframework.core.Ordered; +import org.springframework.util.ClassUtils; + +/** + * Cleans up the logging system immediately after the bootstrap context is created on + * startup. Logging will go dark until the ConfigFileApplicationListener fires, but this + * is the price we pay for that listener being able to adjust the log levels according to + * what it finds in its own configuration. + * + * @author Dave Syer + */ +public class LoggingSystemShutdownListener + implements ApplicationListener, Ordered { + + public static final int DEFAULT_ORDER = BootstrapApplicationListener.DEFAULT_ORDER + + 1; + + private int order = DEFAULT_ORDER; + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + shutdownLogging(); + } + + private void shutdownLogging() { + LoggingSystem loggingSystem = LoggingSystem + .get(ClassUtils.getDefaultClassLoader()); + loggingSystem.cleanUp(); + loggingSystem.beforeInitialize(); + } + + public void setOrder(int order) { + this.order = order; + } + + @Override + public int getOrder() { + return this.order; + } + +} diff --git a/spring-cloud-context/src/main/java/org/springframework/cloud/context/refresh/ContextRefresher.java b/spring-cloud-context/src/main/java/org/springframework/cloud/context/refresh/ContextRefresher.java index 7581de00..2b7b59a3 100644 --- a/spring-cloud-context/src/main/java/org/springframework/cloud/context/refresh/ContextRefresher.java +++ b/spring-cloud-context/src/main/java/org/springframework/cloud/context/refresh/ContextRefresher.java @@ -10,9 +10,10 @@ import java.util.Set; import org.springframework.boot.Banner.Mode; import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.context.config.ConfigFileApplicationListener; +import org.springframework.cloud.bootstrap.BootstrapApplicationListener; import org.springframework.cloud.context.environment.EnvironmentChangeEvent; import org.springframework.cloud.context.scope.refresh.RefreshScope; -import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.CompositePropertySource; @@ -63,8 +64,14 @@ public class ContextRefresher { try { StandardEnvironment environment = copyEnvironment( this.context.getEnvironment()); - capture = new SpringApplicationBuilder(Empty.class).bannerMode(Mode.OFF) - .web(false).environment(environment).run(); + SpringApplicationBuilder builder = new SpringApplicationBuilder(Empty.class) + .bannerMode(Mode.OFF).web(false).environment(environment); + // Just the listeners that affect the environment (e.g. excluding logging + // listener because it has side effects) + builder.application() + .setListeners(Arrays.asList(new BootstrapApplicationListener(), + new ConfigFileApplicationListener())); + capture = builder.run(); if (environment.getPropertySources().contains(REFRESH_ARGS_PROPERTY_SOURCE)) { environment.getPropertySources().remove(REFRESH_ARGS_PROPERTY_SOURCE); } @@ -98,17 +105,9 @@ public class ContextRefresher { } finally { ConfigurableApplicationContext closeable = capture; - while (closeable != null) { - closeable.close(); - ApplicationContext parent = closeable.getParent(); - if (parent instanceof ConfigurableApplicationContext) { - closeable = (ConfigurableApplicationContext) parent; - } - else { - closeable = null; - } - } + closeable.close(); } + } // Don't use ConfigurableEnvironment.merge() in case there are clashes with property @@ -128,7 +127,7 @@ public class ContextRefresher { map.put("spring.jmx.enabled", false); map.put("spring.main.sources", ""); capturedPropertySources - .addFirst(new MapPropertySource(REFRESH_ARGS_PROPERTY_SOURCE, map)); + .addFirst(new MapPropertySource(REFRESH_ARGS_PROPERTY_SOURCE, map)); return environment; } diff --git a/spring-cloud-context/src/main/resources/META-INF/spring.factories b/spring-cloud-context/src/main/resources/META-INF/spring.factories index e770dc28..ddf6a5b0 100644 --- a/spring-cloud-context/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-context/src/main/resources/META-INF/spring.factories @@ -8,6 +8,7 @@ org.springframework.cloud.autoconfigure.LifecycleMvcEndpointAutoConfiguration # Application Listeners org.springframework.context.ApplicationListener=\ org.springframework.cloud.bootstrap.BootstrapApplicationListener,\ +org.springframework.cloud.bootstrap.LoggingSystemShutdownListener,\ org.springframework.cloud.context.restart.RestartListener # Bootstrap components