SpringApplication的属性
private List<ApplicationListener<?>> listeners;
// org.springframework.boot.SpringApplication.SpringApplication(ResourceLoader, Class<?>...)
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
...省略
// 根据反射实例化ApplicationListener实现类,设置为SpringApplication属性
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {
this.listeners = new ArrayList<>();
this.listeners.addAll(listeners);
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
return getSpringFactoriesInstances(type, new Class<?>[] {});
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 根据反射调用ApplicationListener实现类
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
// org.springframework.boot.SpringApplication.run(String...)
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 获取到SpringApplicationRunListeners
SpringApplicationRunListeners listeners = getRunListeners(args);
// SpringApplicationRunListeners.starting(),
// 其实是遍历执行startingSpringApplicationRunListener的starting()
listeners.starting();
...
// 和starting方法一样
listeners.started(context);
return context;
}
// org.springframework.boot.SpringApplication.getRunListeners(String[])
private SpringApplicationRunListeners getRunListeners(String[] args) {
// 根据反射调用SpringApplicationRunListener实现类的带参构造器
// 默认实现类是org.springframework.boot.context.event.EventPublishingRunListener
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
// org.springframework.boot.SpringApplicationRunListeners
public void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
// 遍历所有的SpringApplicationRunListener实例的starting()方法,其他方法类似
listener.starting();
}
}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
// 构造方法,反射调用
public EventPublishingRunListener(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
// 创建一个applicationEvent事件多播器,可以进行广播,即遍历每个ApplicationListener
this.initialMulticaster = new SimpleApplicationEventMulticaster();
// 将SpringApplictaion对象的中的属性listeners(ApplicationListener集合)设置到多播器中
for (ApplicationListener<?> listener : application.getListeners()) {
this.initialMulticaster.addApplicationListener(listener);
}
}
}
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
...
@Override
public void starting() {
// 调用多播器广播事件
this.initialMulticaster.multicastEvent(
new ApplicationStartingEvent(this.application, this.args));
}
...
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
// 遍历SpringApplication中的ApplicationListener集合,设置到context中,查看AbstractApplicationContext.registerListeners()方法会去使用getApplicationListeners获取
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
// 准备好context容器,下一步是要调用AbstractApplicationContext的refresh方法
// 在refresh方法中的initApplicationEventMulticaster方法会初始化Spring自己的多播器,当前类的多播器是属于springboot的
context.addApplicationListener(listener);
}
// 调用多播器广播事件
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
@Override
public void started(ConfigurableApplicationContext context) {
// 调用spring容器的广播事件,后面的running,failed一样
context.publishEvent(
new ApplicationStartedEvent(this.application, this.args, context));
}
...
}
// org.springframework.context.support.AbstractApplicationContext.initApplicationEventMulticaster()
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION_EVENT_MULTICASTER_BEAN_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
// org.springframework.context.support.AbstractApplicationContext.registerListeners()
protected void registerListeners() {
// Register statically specified listeners first.
// 之前在org.springframework.boot.context.event.EventPublishingRunListener.contextLoaded(ConfigurableApplicationContext)设置进容器的
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
// 从容器中取出用户放入的ApplicationListener实现类,但是现在不进行初始化
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
// org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster()
ApplicationEventMulticaster getApplicationEventMulticaster() throws IllegalStateException {
if (this.applicationEventMulticaster == null) {
throw new IllegalStateException("ApplicationEventMulticaster not initialized - " +
"call 'refresh' before multicasting events via the context: " + this);
}
return this.applicationEventMulticaster;
}
// org.springframework.context.event.AbstractApplicationEventMulticaster.addApplicationListener(ApplicationListener<?>)
public void addApplicationListener(ApplicationListener<?> listener) {
synchronized (this.retrievalMutex) {
// Explicitly remove target for a proxy, if registered already,
// in order to avoid double invocations of the same listener.
Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
if (singletonTarget instanceof ApplicationListener) {
this.defaultRetriever.applicationListeners.remove(singletonTarget);
}
this.defaultRetriever.applicationListeners.add(listener);
this.retrieverCache.clear();
}
}
// org.springframework.context.event.AbstractApplicationEventMulticaster.addApplicationListenerBean(ApplicationListener<?>)
@Override
public void addApplicationListenerBean(String listenerBeanName) {
synchronized (this.retrievalMutex) {
this.defaultRetriever.applicationListenerBeans.add(listenerBeanName);
this.retrieverCache.clear();
}
}
// org.springframework.context.event.AbstractApplicationEventMulticaster.ListenerRetriever
private class ListenerRetriever {
public final Set<ApplicationListener<?>> applicationListeners = new LinkedHashSet<>();
public final Set<String> applicationListenerBeans = new LinkedHashSet<>();
...
}
ApplicationListener接口定义
@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
SpringApplicationRunListener接口定义
public interface SpringApplicationRunListener {
/**
* Called immediately when the run method has first started. Can be used for very
* early initialization.
*/
void starting();
/**
* Called once the environment has been prepared, but before the
* {@link ApplicationContext} has been created.
* @param environment the environment
*/
void environmentPrepared(ConfigurableEnvironment environment);
/**
* Called once the {@link ApplicationContext} has been created and prepared, but
* before sources have been loaded.
* @param context the application context
*/
void contextPrepared(ConfigurableApplicationContext context);
/**
* Called once the application context has been loaded but before it has been
* refreshed.
* @param context the application context
*/
void contextLoaded(ConfigurableApplicationContext context);
/**
* The context has been refreshed and the application has started but
* {@link CommandLineRunner CommandLineRunners} and {@link ApplicationRunner
* ApplicationRunners} have not been called.
* @param context the application context.
* @since 2.0.0
*/
void started(ConfigurableApplicationContext context);
/**
* Called immediately before the run method finishes, when the application context has
* been refreshed and all {@link CommandLineRunner CommandLineRunners} and
* {@link ApplicationRunner ApplicationRunners} have been called.
* @param context the application context.
* @since 2.0.0
*/
void running(ConfigurableApplicationContext context);
/**
* Called when a failure occurs when running the application.
* @param context the application context or {@code null} if a failure occurred before
* the context was created
* @param exception the failure
* @since 2.0.0
*/
void failed(ConfigurableApplicationContext context, Throwable exception);
}