共计 8060 个字符,预计需要花费 21 分钟才能阅读完成。
序
本文次要钻研一下 springboot 的启动事件
SpringApplicationEvent
org/springframework/boot/context/event/SpringApplicationEvent.java
public abstract class SpringApplicationEvent extends ApplicationEvent {private final String[] args;
public SpringApplicationEvent(SpringApplication application, String[] args) {super(application);
this.args = args;
}
public SpringApplication getSpringApplication() {return (SpringApplication) getSource();}
public final String[] getArgs() {return this.args;}
}
SpringApplicationEvent 继承了 ApplicationEvent,它有几个子类分表是 ApplicationStartingEvent、ApplicationEnvironmentPreparedEvent、ApplicationContextInitializedEvent、ApplicationPreparedEvent、ApplicationStartedEvent、ApplicationReadyEvent,期间有异样则抛出 ApplicationFailedEvent
SpringApplication.run
org/springframework/boot/SpringApplication.java
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class}, context);
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {listeners.running(context);
}
catch (Throwable ex) {handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
SpringApplication 的 run 办法,先触发 listeners.starting(),而后执行了 prepareEnvironment,之后 createApplicationContext,再进行 prepareContext 和 refreshContext,最初触发 listeners.started(context),之后执行 callRunners,最初触发 listeners.running(context),如有异样则会执行 handleRunFailure
prepareEnvironment
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
configureEnvironment(environment, applicationArguments.getSourceArgs());
ConfigurationPropertySources.attach(environment);
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
prepareEnvironment 会触发 listeners.environmentPrepared(environment),即公布 ApplicationEnvironmentPreparedEvent
prepareContext
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {context.setEnvironment(environment);
postProcessApplicationContext(context);
applyInitializers(context);
listeners.contextPrepared(context);
if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) {context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// Load the sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
}
prepareContext 会触发 listeners.contextPrepared(context),即公布 ApplicationContextInitializedEvent,执行实现之后触发 listeners.contextLoaded(context),即公布 ApplicationPreparedEvent
refreshContext
private void refreshContext(ConfigurableApplicationContext context) {refresh(context);
if (this.registerShutdownHook) {
try {context.registerShutdownHook();
}
catch (AccessControlException ex) {// Not allowed in some environments.}
}
}
protected void refresh(ApplicationContext applicationContext) {Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh();}
refreshContext 会执行 refresh 办法
org/springframework/context/support/AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();}
catch (BeansException ex) {if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization -" +
"cancelling refresh attempt:" + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();}
}
}
refresh 先执行 postProcessBeanFactory,比方增加 BeanPostProcessors,之后执行 invokeBeanFactoryPostProcessors,即执行 BeanFactoryPostProcessor 的 postProcessBeanFactory 办法
refresh 执行完之后触发 listeners.started(context) 即公布 ApplicationStartedEvent
执行完 callRunners 之后触发 listeners.running(context)即公布 ApplicationReadyEvent
handleRunFailure
private void handleRunFailure(ConfigurableApplicationContext context, Throwable exception,
Collection<SpringBootExceptionReporter> exceptionReporters, SpringApplicationRunListeners listeners) {
try {
try {handleExitCode(context, exception);
if (listeners != null) {listeners.failed(context, exception);
}
}
finally {reportFailure(exceptionReporters, exception);
if (context != null) {context.close();
}
}
}
catch (Exception ex) {logger.warn("Unable to close ApplicationContext", ex);
}
ReflectionUtils.rethrowRuntimeException(exception);
}
触发 listeners.failed(context, exception)即公布 ApplicationFailedEvent
小结
SpringApplication 的 run 办法,先触发 listeners.starting()(ApplicationStartingEvent
),而后执行了 prepareEnvironment(ApplicationEnvironmentPreparedEvent
),之后 createApplicationContext,再进行 prepareContext 和 refreshContext(ApplicationContextInitializedEvent
–>ApplicationPreparedEvent
),最初触发 listeners.started(context)(ApplicationStartedEvent
),之后执行 callRunners,最初触发 listeners.running(context)(ApplicationReadyEvent
),期间有异样会执行 handleRunFailure,触发 listeners.failed(context, exception)(ApplicationFailedEvent
)
其中 refresh 的时候会执行 BeanFactoryPostProcessor 的 postProcessBeanFactory 办法
整体程序如下:ApplicationStartingEvent –> ApplicationEnvironmentPreparedEvent –> ApplicationContextInitializedEvent –> ApplicationPreparedEvent –> ApplicationStartedEvent –> ApplicationReadyEvent,期间有异样则抛出 ApplicationFailedEvent