001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.context.event; 018 019import org.apache.commons.logging.Log; 020import org.apache.commons.logging.LogFactory; 021 022import org.springframework.boot.SpringApplication; 023import org.springframework.boot.SpringApplicationRunListener; 024import org.springframework.context.ApplicationContextAware; 025import org.springframework.context.ApplicationListener; 026import org.springframework.context.ConfigurableApplicationContext; 027import org.springframework.context.event.ApplicationEventMulticaster; 028import org.springframework.context.event.SimpleApplicationEventMulticaster; 029import org.springframework.context.support.AbstractApplicationContext; 030import org.springframework.core.Ordered; 031import org.springframework.core.env.ConfigurableEnvironment; 032import org.springframework.util.ErrorHandler; 033 034/** 035 * {@link SpringApplicationRunListener} to publish {@link SpringApplicationEvent}s. 036 * <p> 037 * Uses an internal {@link ApplicationEventMulticaster} for the events that are fired 038 * before the context is actually refreshed. 039 * 040 * @author Phillip Webb 041 * @author Stephane Nicoll 042 * @author Andy Wilkinson 043 * @author Artsiom Yudovin 044 */ 045public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { 046 047 private final SpringApplication application; 048 049 private final String[] args; 050 051 private final SimpleApplicationEventMulticaster initialMulticaster; 052 053 public EventPublishingRunListener(SpringApplication application, String[] args) { 054 this.application = application; 055 this.args = args; 056 this.initialMulticaster = new SimpleApplicationEventMulticaster(); 057 for (ApplicationListener<?> listener : application.getListeners()) { 058 this.initialMulticaster.addApplicationListener(listener); 059 } 060 } 061 062 @Override 063 public int getOrder() { 064 return 0; 065 } 066 067 @Override 068 public void starting() { 069 this.initialMulticaster.multicastEvent( 070 new ApplicationStartingEvent(this.application, this.args)); 071 } 072 073 @Override 074 public void environmentPrepared(ConfigurableEnvironment environment) { 075 this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent( 076 this.application, this.args, environment)); 077 } 078 079 @Override 080 public void contextPrepared(ConfigurableApplicationContext context) { 081 this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent( 082 this.application, this.args, context)); 083 } 084 085 @Override 086 public void contextLoaded(ConfigurableApplicationContext context) { 087 for (ApplicationListener<?> listener : this.application.getListeners()) { 088 if (listener instanceof ApplicationContextAware) { 089 ((ApplicationContextAware) listener).setApplicationContext(context); 090 } 091 context.addApplicationListener(listener); 092 } 093 this.initialMulticaster.multicastEvent( 094 new ApplicationPreparedEvent(this.application, this.args, context)); 095 } 096 097 @Override 098 public void started(ConfigurableApplicationContext context) { 099 context.publishEvent( 100 new ApplicationStartedEvent(this.application, this.args, context)); 101 } 102 103 @Override 104 public void running(ConfigurableApplicationContext context) { 105 context.publishEvent( 106 new ApplicationReadyEvent(this.application, this.args, context)); 107 } 108 109 @Override 110 public void failed(ConfigurableApplicationContext context, Throwable exception) { 111 ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, 112 this.args, context, exception); 113 if (context != null && context.isActive()) { 114 // Listeners have been registered to the application context so we should 115 // use it at this point if we can 116 context.publishEvent(event); 117 } 118 else { 119 // An inactive context may not have a multicaster so we use our multicaster to 120 // call all of the context's listeners instead 121 if (context instanceof AbstractApplicationContext) { 122 for (ApplicationListener<?> listener : ((AbstractApplicationContext) context) 123 .getApplicationListeners()) { 124 this.initialMulticaster.addApplicationListener(listener); 125 } 126 } 127 this.initialMulticaster.setErrorHandler(new LoggingErrorHandler()); 128 this.initialMulticaster.multicastEvent(event); 129 } 130 } 131 132 private static class LoggingErrorHandler implements ErrorHandler { 133 134 private static Log logger = LogFactory.getLog(EventPublishingRunListener.class); 135 136 @Override 137 public void handleError(Throwable throwable) { 138 logger.warn("Error calling ApplicationEventListener", throwable); 139 } 140 141 } 142 143}