承接上文:https://blog.csdn.net/sql2008help/article/details/123253292
上篇文章中主要解析了 SpringApplication 的初始化过程,其中重要的一点是读取 META-INF/spring.factories 配置并缓存至 SpringFactoriesLoader.cache ,cache类型为 Map
以下 run 方法为SpringApplication 的实例方法:
public ConfigurableApplicationContext run(String... args) {
long startTime = System.nanoTime();
//创建引导程序上下文
DefaultBootstrapContext bootstrapContext = this.createBootstrapContext();
ConfigurableApplicationContext context = null;
this.configureHeadlessProperty();
// 实例化 runListeners 当前spring.factories中只配置了
// org.springframework.boot.context.event.EventPublishingRunListener
SpringApplicationRunListeners listeners = this.getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments);
this.configureIgnoreBeanInfo(environment);
Banner printedBanner = this.printBanner(environment);
// 创建 ConfigurableApplicationContext 应用上下文
context = this.createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, applicationArguments);
Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), timeTakenToStartup);
}
listeners.started(context, timeTakenToStartup);
this.callRunners(context, applicationArguments);
} catch (Throwable var12) {
this.handleRunFailure(context, var12, listeners);
throw new IllegalStateException(var12);
}
try {
Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
listeners.ready(context, timeTakenToReady);
return context;
} catch (Throwable var11) {
this.handleRunFailure(context, var11, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var11);
}
}
this.getRunListeners(args) 方法:
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class>[] types = new Class[]{SpringApplication.class, String[].class};
return new SpringApplicationRunListeners(logger, this.getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args), this.applicationStartup);
}
META-INF/spring.factories 中 SpringApplicationRunListener key对应的value值为EventPublishingRunListener:
# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
以上 this.getSpringFactoriesInstances 方法返回值为 EventPublishingRunListener 实例构成的集合
private Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) {
ClassLoader classLoader = this.getClassLoader();
Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
SpringApplicationRunListeners
class SpringApplicationRunListeners {
private final Log log;
private final List listeners;
private final ApplicationStartup applicationStartup;
SpringApplicationRunListeners(Log log, Collection extends SpringApplicationRunListener> listeners, ApplicationStartup applicationStartup) {
this.log = log;
this.listeners = new ArrayList(listeners);
this.applicationStartup = applicationStartup;
}
}
listeners.starting(bootstrapContext, this.mainApplicationClass); 方法:
依次执行 ApplicationListener(即 SpringApplication listeners ) onApplicationEvent 方法
this.createApplicationContext() 方法:
创建应用上下文:AnnotationConfigServletWebApplicationContext,具体可看:https://blog.csdn.net/sql2008help/article/details/123314453
this.prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner) 方法:
private void prepareContext(DefaultBootstrapContext bootstrapContext, ConfigurableApplicationContext context, ConfigurableEnvironment environment, SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
this.postProcessApplicationContext(context);
//执行 SpringApplication 初始化器initialize方法
this.applyInitializers(context);
listeners.contextPrepared(context);
bootstrapContext.close(context);
if (this.logStartupInfo) {
this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context);
}
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof AbstractAutowireCapableBeanFactory) {
((AbstractAutowireCapableBeanFactory)beanFactory).setAllowCircularReferences(this.allowCircularReferences);
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
}
if (this.lazyInitialization) {
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
Set
SpringApplication applyInitializers 方法:
如下代码获取 SpringApplication List
protected void applyInitializers(ConfigurableApplicationContext context) {
Iterator var2 = this.getInitializers().iterator();
while(var2.hasNext()) {
ApplicationContextInitializer initializer = (ApplicationContextInitializer)var2.next();
Class> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
执行完 applyInitializers 方法后,AnnotationConfigServletWebApplicationContext context beanFactoryPostProcessors 属性值有所改变,如下:
listeners.contextPrepared(context) 方法:
即调用 SpringApplicationRunListeners contextPrepared 方法,调用顺序如下:
void contextPrepared(ConfigurableApplicationContext context) {
this.doWithListeners("spring.boot.application.context-prepared", (listener) -> {
// 如下 this.listeners.forEach(listenerAction); 最终会调用此方法,
// 当前只有EventPublishingRunListener实现了SpringApplicationRunListener接口
listener.contextPrepared(context);
});
}
private void doWithListeners(String stepName, Consumer listenerAction) {
this.doWithListeners(stepName, listenerAction, (Consumer)null);
}
private void doWithListeners(String stepName, Consumer listenerAction, Consumer stepAction) {
StartupStep step = this.applicationStartup.start(stepName);
this.listeners.forEach(listenerAction);
if (stepAction != null) {
stepAction.accept(step);
}
step.end();
}
package org.springframework.boot.context.event;
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();
Iterator var3 = application.getListeners().iterator();
while(var3.hasNext()) {
ApplicationListener> listener = (ApplicationListener)var3.next();
this.initialMulticaster.addApplicationListener(listener);
}
}
public void starting(ConfigurableBootstrapContext bootstrapContext) {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(bootstrapContext, this.application, this.args));
}
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));
}
}
this.load(context, sources.toArray(new Object[0])) 方法:
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 创建读取bean定义的导入类实例
BeanDefinitionLoader loader = this.createBeanDefinitionLoader(this.getBeanDefinitionRegistry(context), sources);
。。。。省略。。。。
// 重点看这个方法
loader.load();
}
load 方法执行完后,beanFactory 中 bean定义 beanDefinitionMap 如下:
具体查看:https://blog.csdn.net/sql2008help/article/details/123346522
this.refreshContext(context) 方法:
具体查看:
https://blog.csdn.net/sql2008help/article/details/123354118