深度挖掘SpringBoot

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)
  1. 缓存中查找监听 this.retrieverCache.get(cacheKey)
  2. 检索出所有的感兴趣的监听 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()
  1. 调用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

面试题

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值