赞
踩
SpringApplicationRunListeners有以下几个成员字段:
//org.apache.commons.logging.Log
private final Log log;
private final List<SpringApplicationRunListener> listeners;
private final ApplicationStartup applicationStartup;
SpringApplicationRunListeners可看作是SpringApplicationRunListener的组合模式实现,SpringApplicationRunListener。SpringApplicationRunListener是SpringApplication运行方法的监听器,SpringApplication每次运行都会创建一个新的SpringApplicationRunListener实例。
ApplicationStartup 来标记应用程序启动期间的步骤,并收集有关执行上下文或其处理时间的数据。
public interface ApplicationStartup { /** * 默认“无操作”ApplicationStartup 实现。 * 此变体旨在最小化开销,并且不记录数据。 */ ApplicationStartup DEFAULT = new DefaultApplicationStartup(); /** * 创建一个新步骤并标记它的开始。步骤名称描述当前操作或阶段。 * 这个技术名称应该是“.”命名空间,并且可以在应用程序启动期间重用于描述同一步骤的其他实例。 * @param name 步骤名称 */ StartupStep start(String name); }
默认“无操作”ApplicationStartup 实现。此变体旨在最小化开销,并且不记录事件。
class DefaultApplicationStartup implements ApplicationStartup { private static final DefaultStartupStep DEFAULT_STARTUP_STEP = new DefaultStartupStep(); @Override public DefaultStartupStep start(String name) { return DEFAULT_STARTUP_STEP; } static class DefaultStartupStep implements StartupStep { private final DefaultTags TAGS = new DefaultTags(); @Override public String getName() { return "default"; } @Override public long getId() { return 0L; } @Override public Long getParentId() { return null; } @Override public Tags getTags() { return this.TAGS; } @Override public StartupStep tag(String key, String value) { return this; } @Override public StartupStep tag(String key, Supplier<String> value) { return this; } @Override public void end() { } static class DefaultTags implements StartupStep.Tags { @Override public Iterator<StartupStep.Tag> iterator() { return Collections.emptyIterator(); } } } }
DefaultApplicationStartup的静态内部类DefaultStartupStep实现了StartupStep接口。SpringApplicationRunListeners的environmentPrepared方法源码:
void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) { doWithListeners("spring.boot.application.environment-prepared", (listener) -> listener.environmentPrepared(bootstrapContext, environment)); } private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction) { doWithListeners(stepName, listenerAction, null); } private void doWithListeners(String stepName, Consumer<SpringApplicationRunListener> listenerAction, Consumer<StartupStep> stepAction) { StartupStep step = this.applicationStartup.start(stepName); this.listeners.forEach(listenerAction); if (stepAction != null) { stepAction.accept(step); } step.end(); }
这里调用的是DefaultApplicationStartup的start方法,必须通过DefaultApplicationStartup的start方法才能访问DefaultStartupStep。
private static final DefaultStartupStep DEFAULT_STARTUP_STEP = new DefaultStartupStep();
@Override
public DefaultStartupStep start(String name) {
return DEFAULT_STARTUP_STEP;
}
我们来看看doWithListeners(String stepName, Consumer listenerAction)方法,这个方法的第二个参数是一个函数式接口,SpringApplicationRunListeners的environmentPrepared方法对其传入的参数是(listener) -> listener.environmentPrepared(bootstrapContext, environment),所以Consumer的accept方法接收类型是SpringApplicationRunListener。在doWithListeners(String stepName, Consumer listenerAction,Consumer stepAction)方法中,会遍历每一个成员字段listeners,并且调用每一个listener的environmentPrepared方法。
我这里演示的demo只有一个listener实例,类型是EventPublishingRunListener,这个listener来自SpringApplication的getRunListeners方法
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args),
this.applicationStartup);
}
而getRunListeners又调用了getSpringFactoriesInstances加载了spring-boot-2.6.3.jar中的spring.factories文件key是SpringApplicationRunListener的实例。
SpringApplicationRunListener 发布 SpringApplicationEvents。对在实际刷新上下文之前触发的事件使用内部 ApplicationEventMulticaster。
EventPublishingRunListener的源码:
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered { private final SpringApplication application; private final String[] args; private final SimpleApplicationEventMulticaster initialMulticaster; public EventPublishingRunListener(SpringApplication application, String[] args) { this.application = application; this.args = args; this.initialMulticaster = new SimpleApplicationEventMulticaster(); for (ApplicationListener<?> listener : application.getListeners()) { this.initialMulticaster.addApplicationListener(listener); } } @Override public int getOrder() { return 0; } @Override public void starting(ConfigurableBootstrapContext bootstrapContext) { this.initialMulticaster .multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args)); } @Override public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) { this.initialMulticaster.multicastEvent( new ApplicationEnvironmentPreparedEvent(bootstrapContext, this.application, this.args, environment)); } @Override public void contextPrepared(ConfigurableApplicationContext context) { this.initialMulticaster .multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context)); } @Override public void contextLoaded(ConfigurableApplicationContext context) { for (ApplicationListener<?> listener : this.application.getListeners()) { if (listener instanceof ApplicationContextAware) { ((ApplicationContextAware) listener).setApplicationContext(context); } context.addApplicationListener(listener); } this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context)); } @Override public void started(ConfigurableApplicationContext context, Duration timeTaken) { context.publishEvent(new ApplicationStartedEvent(this.application, this.args, context, timeTaken)); AvailabilityChangeEvent.publish(context, LivenessState.CORRECT); } @Override public void ready(ConfigurableApplicationContext context, Duration timeTaken) { context.publishEvent(new ApplicationReadyEvent(this.application, this.args, context, timeTaken)); AvailabilityChangeEvent.publish(context, ReadinessState.ACCEPTING_TRAFFIC); } @Override public void failed(ConfigurableApplicationContext context, Throwable exception) { ApplicationFailedEvent event = new ApplicationFailedEvent(this.application, this.args, context, exception); if (context != null && context.isActive()) { // Listeners have been registered to the application context so we should // use it at this point if we can context.publishEvent(event); } else { // An inactive context may not have a multicaster so we use our multicaster to // call all of the context's listeners instead if (context instanceof AbstractApplicationContext) { for (ApplicationListener<?> listener : ((AbstractApplicationContext) context) .getApplicationListeners()) { this.initialMulticaster.addApplicationListener(listener); } } this.initialMulticaster.setErrorHandler(new LoggingErrorHandler()); this.initialMulticaster.multicastEvent(event); } } private static class LoggingErrorHandler implements ErrorHandler { private static final Log logger = LogFactory.getLog(EventPublishingRunListener.class); @Override public void handleError(Throwable throwable) { logger.warn("Error calling ApplicationEventListener", throwable); } } }
我们在EventPublishingRunListener的构造方法中可以看到传入了SpringApplication,一个EventPublishingRunListener对应一个SpringApplication。而一个SpringApplication中包含多个监听器(Listeners)。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。