diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationReportLoggingInitializer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationReportLoggingInitializer.java index e261f2df2c..6ca81f8512 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationReportLoggingInitializer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/AutoConfigurationReportLoggingInitializer.java @@ -36,10 +36,9 @@ import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; /** - * {@link ApplicationContextInitializer} and {@link SmartApplicationListener} that writes - * the {@link AutoConfigurationReport} to the log. Reports are logged at the - * {@link LogLevel#DEBUG DEBUG} level unless there was a problem, in which case they are - * the {@link LogLevel#INFO INFO} level is used. + * {@link ApplicationContextInitializer} that writes the {@link AutoConfigurationReport} + * to the log. Reports are logged at the {@link LogLevel#DEBUG DEBUG} level unless there + * was a problem, in which case they are the {@link LogLevel#INFO INFO} level is used. *

* This initializer is not intended to be shared across multiple application context * instances. @@ -49,8 +48,7 @@ import org.springframework.util.StringUtils; * @author Phillip Webb */ public class AutoConfigurationReportLoggingInitializer implements - ApplicationContextInitializer, - SmartApplicationListener { + ApplicationContextInitializer { private final Log logger = LogFactory.getLog(getClass()); @@ -58,14 +56,10 @@ public class AutoConfigurationReportLoggingInitializer implements private AutoConfigurationReport report; - @Override - public int getOrder() { - return Ordered.LOWEST_PRECEDENCE; - } - @Override public void initialize(ConfigurableApplicationContext applicationContext) { this.applicationContext = applicationContext; + applicationContext.addApplicationListener(new AutoConfigurationReportListener()); if (applicationContext instanceof GenericApplicationContext) { // Get the report early in case the context fails to load this.report = AutoConfigurationReport.get(this.applicationContext @@ -73,26 +67,14 @@ public class AutoConfigurationReportLoggingInitializer implements } } - @Override - public boolean supportsEventType(Class type) { - return ContextRefreshedEvent.class.isAssignableFrom(type) - || ApplicationFailedEvent.class.isAssignableFrom(type); - } - - @Override - public boolean supportsSourceType(Class sourceType) { - return true; - } - - @Override - public void onApplicationEvent(ApplicationEvent event) { + protected void onApplicationEvent(ApplicationEvent event) { if (event instanceof ContextRefreshedEvent) { - if (((ApplicationContextEvent) event).getApplicationContext() == this.applicationContext) { + if (((ApplicationContextEvent) event).getApplicationContext() == AutoConfigurationReportLoggingInitializer.this.applicationContext) { logAutoConfigurationReport(); } } else if (event instanceof ApplicationFailedEvent) { - if (((ApplicationFailedEvent) event).getApplicationContext() == this.applicationContext) { + if (((ApplicationFailedEvent) event).getApplicationContext() == AutoConfigurationReportLoggingInitializer.this.applicationContext) { logAutoConfigurationReport(true); } } @@ -171,4 +153,27 @@ public class AutoConfigurationReportLoggingInitializer implements } + private class AutoConfigurationReportListener implements SmartApplicationListener { + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } + + @Override + public boolean supportsEventType(Class type) { + return ContextRefreshedEvent.class.isAssignableFrom(type) + || ApplicationFailedEvent.class.isAssignableFrom(type); + } + + @Override + public boolean supportsSourceType(Class sourceType) { + return true; + } + + @Override + public void onApplicationEvent(ApplicationEvent event) { + AutoConfigurationReportLoggingInitializer.this.onApplicationEvent(event); + } + } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SecurityAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SecurityAutoConfigurationTests.java index d96a874247..d30f1b7e11 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SecurityAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/SecurityAutoConfigurationTests.java @@ -29,7 +29,6 @@ import org.springframework.boot.event.ApplicationPreparedEvent; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.mock.web.MockServletContext; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.security.authentication.AuthenticationManager; @@ -124,7 +123,6 @@ public class SecurityAutoConfigurationTests { AutoConfigurationReportLoggingInitializer initializer = new AutoConfigurationReportLoggingInitializer(); initializer.initialize(context); context.refresh(); - initializer.onApplicationEvent(new ContextRefreshedEvent(context)); return context; } 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 9736f2c30b..0be2509be4 100644 --- a/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java +++ b/spring-boot/src/main/java/org/springframework/boot/SpringApplication.java @@ -139,7 +139,6 @@ import org.springframework.web.context.support.StandardServletEnvironment; *

  • {@link CharSequence} - A class name, resource handle or package name to loaded as * appropriate. If the {@link CharSequence} cannot be resolved to class and does not * resolve to a {@link Resource} that exists it will be considered a {@link Package}.
  • - * * * * @author Phillip Webb @@ -183,9 +182,9 @@ public class SpringApplication { private boolean headless = true; - private Set> initializers; + private List> initializers; - private Set> listeners; + private List> listeners; private Map defaultProperties; @@ -219,29 +218,14 @@ public class SpringApplication { initialize(sources); } + @SuppressWarnings({ "unchecked", "rawtypes" }) private void initialize(Object[] sources) { if (sources != null && sources.length > 0) { this.sources.addAll(Arrays.asList(sources)); } this.webEnvironment = deduceWebEnvironment(); - this.initializers = new LinkedHashSet>(); - this.listeners = new LinkedHashSet>(); - @SuppressWarnings("unchecked") - Collection> initializers = (Collection>) getSpringFactoriesInstances(ApplicationContextInitializer.class); - this.initializers.addAll(initializers); - for (ApplicationContextInitializer initializer : initializers) { - if (initializer instanceof ApplicationListener) { - addListeners((ApplicationListener) initializer); - } - } - @SuppressWarnings("unchecked") - Collection> listeners = (Collection>) getSpringFactoriesInstances(ApplicationListener.class); - this.listeners.addAll(listeners); - for (ApplicationListener listener : listeners) { - if (listener instanceof ApplicationContextInitializer) { - addInitializers((ApplicationContextInitializer) listener); - } - } + setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); + setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); this.mainApplicationClass = deduceMainApplicationClass(); } @@ -316,7 +300,7 @@ public class SpringApplication { ApplicationEventMulticaster multicaster = createApplicationEventMulticaster(); try { Set sources = getSources(); - registerListeners(multicaster, sources); + registerListenerAndInitializerSources(multicaster, sources); // Allow logging and stuff to initialize very early multicaster.multicastEvent(new ApplicationStartedEvent(this, args)); @@ -341,7 +325,7 @@ public class SpringApplication { } // Some sources might be listeners - registerListeners(multicaster, sources); + registerListenerAndInitializerSources(multicaster, sources); // Create, load, refresh and run the ApplicationContext context = createApplicationContext(); @@ -404,8 +388,8 @@ public class SpringApplication { } } - private void registerListeners(ApplicationEventMulticaster multicaster, - Set sources) { + private void registerListenerAndInitializerSources( + ApplicationEventMulticaster multicaster, Set sources) { for (Object object : sources) { if (object instanceof ApplicationListener) { multicaster.addApplicationListener((ApplicationListener) object); @@ -428,7 +412,7 @@ public class SpringApplication { } private ApplicationEventMulticaster createApplicationEventMulticaster() { - final ApplicationEventMulticaster multicaster = new SpringApplicationEventMulticaster(); + ApplicationEventMulticaster multicaster = new SpringApplicationEventMulticaster(); for (ApplicationListener listener : getListeners()) { multicaster.addApplicationListener(listener); } @@ -831,83 +815,50 @@ public class SpringApplication { /** * Sets the {@link ApplicationContextInitializer} that will be applied to the Spring - * {@link ApplicationContext}. Any existing initializers will be replaced. Any - * initializers that are also {@link ApplicationListener} will be added to the - * {@link #addListeners(ApplicationListener...) listeners} automatically + * {@link ApplicationContext}. * @param initializers the initializers to set */ public void setInitializers( Collection> initializers) { - this.initializers = new LinkedHashSet>( - initializers); - for (ApplicationContextInitializer initializer : initializers) { - if (initializer instanceof ApplicationListener) { - this.listeners.add((ApplicationListener) initializer); - } - } + this.initializers = new ArrayList>(); + this.initializers.addAll(initializers); } /** * Add {@link ApplicationContextInitializer}s to be applied to the Spring - * {@link ApplicationContext}. Any initializers that are also - * {@link ApplicationListener} will be added to the - * {@link #addListeners(ApplicationListener...) listeners} automatically. + * {@link ApplicationContext}. * @param initializers the initializers to add */ public void addInitializers(ApplicationContextInitializer... initializers) { this.initializers.addAll(Arrays.asList(initializers)); - for (ApplicationContextInitializer initializer : initializers) { - if (initializer instanceof ApplicationListener) { - this.listeners.add((ApplicationListener) initializer); - } - } } /** - * Returns readonly set of the {@link ApplicationContextInitializer}s that will be + * Returns read-only set of the {@link ApplicationContextInitializer}s that will be * applied to the Spring {@link ApplicationContext}. * @return the initializers */ public Set> getInitializers() { - ArrayList> list = new ArrayList>( - this.initializers); - AnnotationAwareOrderComparator.sort(list); - return Collections - .unmodifiableSet(new LinkedHashSet>(list)); + return asUnmodifiableSortedSet(this.initializers); } /** * Sets the {@link ApplicationListener}s that will be applied to the SpringApplication - * and registered with the {@link ApplicationContext}. Any existing listeners will be - * replaced. Any listeners that are also {@link ApplicationContextInitializer} will be - * added to the {@link #addInitializers(ApplicationContextInitializer...) - * initializers} automatically. + * and registered with the {@link ApplicationContext}. * @param listeners the listeners to set */ public void setListeners(Collection> listeners) { - this.listeners = new LinkedHashSet>(listeners); - for (ApplicationListener listener : listeners) { - if (listener instanceof ApplicationContextInitializer) { - this.initializers.add((ApplicationContextInitializer) listener); - } - } + this.listeners = new ArrayList>(); + this.listeners.addAll(listeners); } /** * Add {@link ApplicationListener}s to be applied to the SpringApplication and - * registered with the {@link ApplicationContext}. Any listeners that are also - * {@link ApplicationContextInitializer} will be added to the - * {@link #addInitializers(ApplicationContextInitializer...) initializers} - * automatically. + * registered with the {@link ApplicationContext}. * @param listeners the listeners to add */ public void addListeners(ApplicationListener... listeners) { this.listeners.addAll(Arrays.asList(listeners)); - for (ApplicationListener listener : listeners) { - if (listener instanceof ApplicationContextInitializer) { - this.initializers.add((ApplicationContextInitializer) listener); - } - } } /** @@ -916,11 +867,7 @@ public class SpringApplication { * @return the listeners */ public Set> getListeners() { - ArrayList> list = new ArrayList>( - this.listeners); - AnnotationAwareOrderComparator.sort(list); - return Collections - .unmodifiableSet(new LinkedHashSet>(list)); + return asUnmodifiableSortedSet(this.listeners); } /** @@ -1018,6 +965,17 @@ public class SpringApplication { } } + private static Set asUnmodifiableSortedSet(Collection elemements) { + List list = new ArrayList(); + list.addAll(elemements); + Collections.sort(list, AnnotationAwareOrderComparator.INSTANCE); + return new LinkedHashSet(list); + } + + /** + * {@link ApplicationEventMulticaster} and {@link ApplicationEventPublisher} for + * {@link SpringApplication} events. + */ private static class SpringApplicationEventMulticaster extends SimpleApplicationEventMulticaster implements ApplicationEventPublisher { diff --git a/spring-boot/src/main/java/org/springframework/boot/context/initializer/ParentContextApplicationContextInitializer.java b/spring-boot/src/main/java/org/springframework/boot/context/initializer/ParentContextApplicationContextInitializer.java index 4cd5d70381..cc40517457 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/initializer/ParentContextApplicationContextInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/initializer/ParentContextApplicationContextInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2012 the original author or authors. + * Copyright 2010-2014 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. @@ -32,10 +32,9 @@ import org.springframework.core.Ordered; * @author Dave Syer */ public class ParentContextApplicationContextInitializer implements - ApplicationContextInitializer, - ApplicationListener, Ordered { + ApplicationContextInitializer, Ordered { - private int order = Integer.MIN_VALUE; + private int order = Ordered.HIGHEST_PRECEDENCE; private final ApplicationContext parent; @@ -52,18 +51,30 @@ public class ParentContextApplicationContextInitializer implements return this.order; } - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - ApplicationContext context = event.getApplicationContext(); - if (context instanceof ConfigurableApplicationContext) { - context.publishEvent(new ParentContextAvailableEvent( - (ConfigurableApplicationContext) context)); - } - } - @Override public void initialize(ConfigurableApplicationContext applicationContext) { applicationContext.setParent(this.parent); + applicationContext.addApplicationListener(EventPublisher.INSTANCE); + } + + private static class EventPublisher implements + ApplicationListener, Ordered { + + private static EventPublisher INSTANCE = new EventPublisher(); + + @Override + public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + ApplicationContext context = event.getApplicationContext(); + if (context instanceof ConfigurableApplicationContext) { + context.publishEvent(new ParentContextAvailableEvent( + (ConfigurableApplicationContext) context)); + } + } } public static class ParentContextAvailableEvent extends ApplicationEvent { diff --git a/spring-boot/src/main/java/org/springframework/boot/context/listener/ParentContextCloserListener.java b/spring-boot/src/main/java/org/springframework/boot/context/listener/ParentContextCloserApplicationListener.java similarity index 95% rename from spring-boot/src/main/java/org/springframework/boot/context/listener/ParentContextCloserListener.java rename to spring-boot/src/main/java/org/springframework/boot/context/listener/ParentContextCloserApplicationListener.java index afe631646d..f8b6d3d5d2 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/listener/ParentContextCloserListener.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/listener/ParentContextCloserApplicationListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 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. @@ -29,7 +29,7 @@ import org.springframework.core.Ordered; * * @author Dave Syer */ -public class ParentContextCloserListener implements +public class ParentContextCloserApplicationListener implements ApplicationListener, Ordered { @Override diff --git a/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorInitializer.java b/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java similarity index 92% rename from spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorInitializer.java rename to spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java index c2d77538ce..9ba7320917 100644 --- a/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorInitializer.java +++ b/spring-boot/src/main/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListener.java @@ -16,10 +16,10 @@ import org.springframework.util.ClassUtils; * @author Phillip Webb * @author Dave Syer */ -public class LiquibaseServiceLocatorInitializer implements +public class LiquibaseServiceLocatorApplicationListener implements ApplicationListener { - static final Log logger = LogFactory.getLog(LiquibaseServiceLocatorInitializer.class); + static final Log logger = LogFactory.getLog(LiquibaseServiceLocatorApplicationListener.class); @Override public void onApplicationEvent(ApplicationStartedEvent event) { diff --git a/spring-boot/src/main/java/org/springframework/boot/liquibase/SpringPackageScanClassResolver.java b/spring-boot/src/main/java/org/springframework/boot/liquibase/SpringPackageScanClassResolver.java index c9cf370238..6fede4d6b7 100644 --- a/spring-boot/src/main/java/org/springframework/boot/liquibase/SpringPackageScanClassResolver.java +++ b/spring-boot/src/main/java/org/springframework/boot/liquibase/SpringPackageScanClassResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 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. @@ -74,8 +74,8 @@ public class SpringPackageScanClassResolver extends DefaultPackageScanClassResol return ClassUtils.forName(reader.getClassMetadata().getClassName(), loader); } catch (Exception ex) { - if (LiquibaseServiceLocatorInitializer.logger.isWarnEnabled()) { - LiquibaseServiceLocatorInitializer.logger.warn( + if (LiquibaseServiceLocatorApplicationListener.logger.isWarnEnabled()) { + LiquibaseServiceLocatorApplicationListener.logger.warn( "Ignoring cadidate class resource " + resource, ex); } return null; diff --git a/spring-boot/src/main/resources/META-INF/spring.factories b/spring-boot/src/main/resources/META-INF/spring.factories index 02303c4140..18e2f4b106 100644 --- a/spring-boot/src/main/resources/META-INF/spring.factories +++ b/spring-boot/src/main/resources/META-INF/spring.factories @@ -11,6 +11,6 @@ org.springframework.boot.context.listener.EnvironmentDelegateApplicationListener org.springframework.boot.context.listener.FileEncodingApplicationListener,\ org.springframework.boot.context.listener.LoggingApplicationListener,\ org.springframework.boot.context.listener.VcapApplicationListener,\ -org.springframework.boot.context.listener.ParentContextCloserListener,\ -org.springframework.boot.liquibase.LiquibaseServiceLocatorInitializer +org.springframework.boot.context.listener.ParentContextCloserApplicationListener,\ +org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener 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 abf8f96a50..4cefcbf2a4 100644 --- a/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/SpringApplicationTests.java @@ -165,19 +165,13 @@ public class SpringApplicationTests { SpringApplication application = new SpringApplication(ExampleConfig.class); application.setWebEnvironment(false); final AtomicReference reference = new AtomicReference(); - class InitalizerListener implements - ApplicationContextInitializer, - ApplicationListener { + class InitalizerListener implements ApplicationListener { @Override public void onApplicationEvent(ContextRefreshedEvent event) { reference.set(event.getApplicationContext()); } - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - } } - application.setInitializers(Arrays.asList(new InitalizerListener())); + application.setListeners(Arrays.asList(new InitalizerListener())); this.context = application.run("--foo=bar"); assertThat(this.context, sameInstance(reference.get())); // Custom initializers do not switch off the defaults diff --git a/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorInitializerTests.java b/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java similarity index 89% rename from spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorInitializerTests.java rename to spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java index efc3ba2fe6..646fc4e32c 100644 --- a/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorInitializerTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/liquibase/LiquibaseServiceLocatorApplicationListenerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2014 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. @@ -29,11 +29,11 @@ import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertThat; /** - * Tests for {@link LiquibaseServiceLocatorInitializer}. + * Tests for {@link LiquibaseServiceLocatorApplicationListener}. * * @author Phillip Webb */ -public class LiquibaseServiceLocatorInitializerTests { +public class LiquibaseServiceLocatorApplicationListenerTests { @Test public void replacesServiceLocator() throws Exception {