new SpringApplication()创建实例
Create a new {@link SpringApplication} instance
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
WebApplicationType.deduceFromClasspath();
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
实例化SpringApplication流程
- 推断web类型(SERVLET)
- 设置ApplicationContextInitializer
- 利用工厂加载机制实例化ApplicationContextInitializer的子类
- 设置ApplicationListener监听类
- 推到main方法运行的主类
工厂加载机制SpringFactoriesLoader
介绍
- 框架内部通用工厂加载机制
- 从classpath下多个jar包特定的位置读取文件并初始化类
- 文件内容必须k-v形式,即properties类型
- key是全限定名(抽象类|接口)、value是实现、多个实现,分割
SpringApplication.getSpringFactoriesInstances(Xxxx.class);
1.实例化EventPublishingRunListener
//工厂加载机制
SpringFactoriesLoader.loadFactoryNames()
加载流程图
框架启动方法run()
框架启动流程
计时器》Headless模式赋值》发送ApplicationStartingEvent》配置环境模块》打印banner》创建应用上下文对象》初始化失败分析器》关联springboot组件与应用上下文对象》发送ApplicationContextInitializedEvent》加载sources到context》发送ApplicationPreparedEvent》刷新上下文》计时器停止计时》发送ApplicationContextStartedEvent》调用框架启动扩展类==》发送ApplicationReadyEvent
系统初始化器解析ApplicationContextInitializer
调用顺序
-
//应用准备阶段 prepareContext(); //spring中刷新上下文的核心方法 refreshContext(context); // prepareContext(){ ... applyInitializers(); ... }
加载spring.factories中注册在
ApplicationContextInitializer
初始化类
# Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer,\
org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener
调用模板类ApplicationContextInitializer.initialize()方法,完成初始化。
实现步骤:
1.实现ApplicationContextInitializer接口
2.spring.factories内填写接口实现
SpringBoot监听器解析
监听器模式介绍
- 事件
- 监听器
- 广播器
- 触发机制
系统监听器介绍ApplicationListener
-
事件
ApplicationEvent
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X9sPJo9l-1593612510738)(C:\Users\ACER\AppData\Roaming\Typora\typora-user-images\image-20200629190925223.png)]
-
监听器
interface ApplicationListener
-
广播器
interface ApplicationEventMulticaster
监听器注册
同上系统初始化注册,通过SpringFactories.loadFactoryNames()加载配置在spring.factories中的ApplicationListener.class的实现类
监听事件触发机制
***以run()中的SpringApplicationRunListener为例子
-
SpringApplicationRunListeners listeners = getRunListeners(args);
-
listeners.starting(); //SpringApplicationRunListener的集合
- listener.starting(); //开启入口,实现在EventPublishingRunListener
@Override
public void starting() {
this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
}
//由事件广播发布ApplicationStartingEvent事件
//event:事件本身,eventType:shiji
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
//根据事件获取对应的监听对象getApplicationListeners()
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
//触发监听器
invokeListener(listener, event);
}
}
}
ResolvableType代表事件的类型解析,ApplicationEvent代表事件本身
1.获取监听getApplicationListeners(ApplicationEvent event, ResolvableType eventType)
- 缓存中查找监听 this.retrieverCache.get(cacheKey)
- 检索出所有的感兴趣的监听 retrieveApplicationListeners(eventType, sourceType, retriever);
1.1监听检索retrieveApplicationListeners()
1.1.1加载所有监听
1.1.2遍历监听,筛选出对事件感兴趣的监听supportsEvent(listener, eventType, sourceType);
listener intanceof GenericApplicationListener;不属于则使用适配器转换为GenericApplicationListener类型,最后判断是否支持事件来判断是否感兴趣,后面的一个判断一般为true; (smartListener.supportsEventType(eventType) && smartListener.supportsSourceType(sourceType))
1.1.3将感兴趣的监听加入到监听检索ListenerRetriever中。
1.1.4监听排序
1.2将监听加入到索引缓存retrieverCache
2.调用监听invokeListener()
- 调用ApplicationListener中唯一的监听调用方法listener.onApplicationEvent(event);
SpringBoot Banner
配置文件配置banner的位置
banner获取原理
run方法代码入口: Banner printedBanner = printBanner(environment);
核心类:资源加载ResourceLoader、banner包装Banner、输出PrintStream
计时器
run方法代码入口:
StopWatch stopWatch = new StopWatch();
stopWatch.start();
stopWatch.stop();
启动加载器
可以在springboot启动后加载。
run方法代码入口:callRunners(context, applicationArguments);
方法实现方式
- 添加ApplicationRunner实现至runners中
- 添加CommondLineRunner实现至runners中
- 对runners集合排序
- 遍历调用实现类的run方法
自定义实现方式
- 继承实现CommandLineRunner
- 继承实现ApplicationRunner
面试题