深度挖掘SpringBoot

    技术2022-07-11  82

    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

    面试题

    Processed: 0.014, SQL: 9