spring-boot-2.0.3不一样系列之源码篇 - 阶段总结

前言

  开心一刻

    朋友喜欢去按摩,第一次推门进来的是一个学生美眉,感觉还不错;后来经常去,有时是护士,有时是空姐,有时候是教师。昨天晚上推门进去的是一个女警察,长得贼好看,身材也很好,朋友嗷的一声就扑上去了。然后他就被抓起来了,罪名是:嫖娼、袭警、强奸未遂。

  路漫漫其修远兮,吾将上下而求索!

  github:https://github.com/youzhibing

  码云(gitee):https://gitee.com/youzhibing

前情回顾

springboot2.3源码篇之SpringApplication的构造方法

    主要做了两件事:

    1、推测应用类型

      根据类路径下是否存在指定类型的类来断定应用类型;

      应用类型有三种:NONE、SERVLET、REACTIVE,NONO表示普通的java应用,SERVLET表示基于servlet 的web工程,REACTIVE表示 reactive web application(还没去了解,囧...)

    2、获取ApplicationContextInitializer、ApplicationListener实例

      查找类路径下全部的META-INF/spring.factories的URL(spring.factories文件的路径),并加载所有spring.factories中的内容(包括各种Initializer、ApplicationListener、AutoConfigure、Failure analyzers等)到SpringFactoriesLoader的cache中;

      然后从缓存中获取ApplicationContextInitializer、ApplicationListener类型的类并进行实例化,然后将得到的实例化集合分别赋值给SpringApplication的initializers和listeners

springboot2.3源码篇之run方法(一):SpringApplicationRunListener

    主要做了两件事:

    1、准备好运行时监听器:EventPublishingRunListener,并过滤出于与ApplicationStartingEvent匹配的监听器

    2、广播ApplicationStartingEvent事件,触发对应的事件监听器

      LoggingApplicationListener

        检测正在使用的日志系统

      BackgroundPreinitializer

        另起一个后台线程执行耗时的初始化

springboot2.3源码篇之run方法(二):prepareEnvironment方法

    1、获取或创建环境

      根据SpringApplication构造方法中推断出的应用类型创建对应的环境,一般而言是web环境:StandardServletEnvironment

    2、广播ApplicationEnvironmentPreparedEvent事件,触发相应的监听器

      ConfigFileApplicationListener

        添加名叫random的RandomValuePropertySource到environment

        添加名叫applicationConfig:[classpath:/application.yml]的OriginTrackedMapPropertySource到environment

      LoggingApplicationListener

        初始化日志系统

    3、加载外部化配置的资源到environment

      包括命令行参数、servletConfigInitParams、servletContextInitParams、systemProperties、sytemEnvironment、random、application.yml(.yaml/.xml/.properties)等

springboot2.3源码篇之run方法(三):createApplicationContext方法

    1、实例化应用上下文

      应用类型有三种,对应的上下文也有三种,NONE -> AnnotationConfigApplicationContext,SERVLET -> AnnotationConfigServletWebServerApplicationContext,REACTIVE -> AnnotationConfigReactiveWebServerApplicationContext;一般而言,创建的是AnnotationConfigServletWebServerApplicationContext。

    2、实例化AnnotatedBeanDefinitionReader、ClassPathBeanDefinitionScanner和DefaultListableBeanFactory

      AnnotatedBeanDefinitionReader是注解bean定义读取器,用于编程式注解bean的注册;ClassPathBeanDefinitionScanner是类路径bean定义扫描器,用于检测类路径上的bean候选者。

      AnnotatedBeanDefinitionReade用来加载class类型的配置,在它初始化的时候,会预先注册一些BeanPostProcessor和BeanFactoryPostProcessor,这些处理器会在接下来的spring初始化流程中被调用。ClassPathBeanDefinitionScanner是一个扫描指定类路径中注解Bean定义的扫描器,在它初始化的时候,会初始化一些需要被扫描的注解。

      DefaultListableBeanFactory,也就是我们所说的beanFactory,用来注册所有bean定义(bean definitions),也可以用来作为单例bean工厂。

springboot2.3源码篇之run方法(四):prepareContext方法

    1、将SpringApplication中的部分属性应用到上下文中

      SpringApplication中的environment、initializers、listeners应用到spring上下文中

    2、广播ApplicationPreparedEvent事件,触发对应的事件监听器

      向context的beanFactoryPostProcessors中注册了一个PropertySourceOrderingPostProcessor实例       向beanFactory中注册了一个名叫springBootLoggingSystem的单例bean,也就是我们的日志系统bean

    3、加载资源

      支持4种方式:Class、Resource、Package和CharSequence。

        Class:注解形式的Bean定义;AnnotatedBeanDefinitionReader负责处理。

        Resource:一般而言指的是xml bean配置文件,也就是我们在spring中常用的xml配置。说的简单点就是:将xml的bean定义封装成BeanDefinition并注册到beanFactory的BeanDefinitionMap中;XmlBeanDefinitionReader负责处理。

        Package:以扫包的方式扫描bean定义; ClassPathBeanDefinitionScanner负责处理。

        CharSequence:以先后顺序进行匹配Class、Resource或Package进行加载,谁匹配上了就用谁的处理方式处理。

      springboot鼓励用java类实现java bean定义,所以springboot应用中,我们一般只需要关注Class方式、Package方式即可。

    context中主要是三个属性增加了内容:beanFactory、beanFactoryPostProcessors和applicationListeners

三个事件

  ApplicationStartingEvent

    在监听器注册完、SpringApplication构造完后,以及其他的任何处理之前被广播,触发对应的事件监听器

  ApplicationEnvironmentPreparedEvent

    environment创建后,context创建之前被广播,触发对应的事件监听器   ApplicationPreparedEvent

    bean定义加载后,上下文refresh之前被广播,触发对应的事件监听器

  后续还会涉及到ApplicationReadyEvent、ApplicationFailedEvent事件,后续再详解

  关于事件机制,可到此处查看更多详情

三个核心

SpringApplication

    springboot的特性之一,内容如下    

      23. SpringApplication         23.1. Startup Failure         23.2. Customizing the Banner         23.3. Customizing SpringApplication         23.4. Fluent Builder API         23.5. Application Events and Listeners         23.6. Web Environment         23.7. Accessing Application Arguments         23.8. Using the ApplicationRunner or CommandLineRunner         23.9. Application Exit         23.10. Admin Features

    也是springboot中比较重要的特性之一,用于从java main方法引导和启动Spring应用程序。其实给我印象最深的还是从spring.factories加载一系列的类,包括Initializer、ApplicationListener、AutoConfigure、Failure analyzers等等,springboot的自动配置,从此时已经开始了,一系列的AutoConfigure都是从spring.factories获取的。   environment:StandardServletEnvironment

    表示当前应用程序所处的环境,主要包括两方面:profiles和properties;例如我们经常说的本地、运测、预发布、生产环境,就可以通过environment进行配置,以及是否是web环境。

    一般而言,我们的环境是StandardServletEnvironment,标准的servlet环境,也就是我们经常说的web环境

  ApplicationContext:AnnotationConfigServletWebServerApplicationContext

    应用上下文,用于为应用程序提供配置的中央接口,提供如下内容:

      1、访问应用程序组件的Bean工厂方法

      2、加载文件资源的能力

      3、发布事件到已注册的事件监听器的能力

      4、解析消息,支持国际化的能力

      等等一系列的功能

    AnnotationConfigServletWebServerApplicationContext是springboot对spring应用上下文的拓展,引入了一些springboot的内容。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏黑泽君的专栏

Ecplise设置全局编码为UTF-8的方法

如果要使插件开发应用能有更好的国际化支持,能够最大程度的支持中文输出,则最好让Java文件使用UTF-8编码。

772
来自专栏JAVA高级架构

Java面试分享(题目+答案)

2843
来自专栏陈树义

Dubbo配置方式详解

Dubbo 是一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,是阿里巴巴 SOA 服务化治理方案的核心框架,每天为 2,000+ 个...

4115
来自专栏magicsoar

html5利用websocket完成的推送功能(tomcat)

利用websocket和java完成的消息推送功能,服务器用的是tomcat7.0.42,一些东西是自己琢磨的,也不知道恰不恰当,不恰当处,还请各位见谅,并指出...

5116
来自专栏依乐祝

ASP.NET Core WebApi使用Swagger生成api说明文档看这篇就够了

将 Swagger 生成器添加到 Startup.ConfigureServices 方法中的服务集合中:

2331
来自专栏JAVA同学会

Zookeeper应用之——栅栏(barrier)

barrier的作用是所有的线程等待,知道某一时刻,锁释放,所有的线程同时执行。举一个生动的例子,比如跑步比赛,所有

993
来自专栏java思维导图

mybatis-plus思维导图,让mybatis-plus不再难懂

 Mybatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果...

1.3K18
来自专栏高性能服务器开发

(五)如何编写高性能日志

一、服务器端日志与客户端日志的区别 在正式讲解之前,我们先来看一个日志类的实现方法,这个日志类也是代表着大多数客户端日志的主流写法: /** *@desc:...

4158
来自专栏JAVA同学会

Zookeeper应用之——栅栏(barrier)

barrier的作用是所有的线程等待,知道某一时刻,锁释放,所有的线程同时执行。举一个生动的例子,比如跑步比赛,所有 运动员都要在起跑线上等待,直到枪声响后,所...

821
来自专栏JetpropelledSnake

Python入门之logging模块

本章目录:     一、logging模块简介     二、logging模块的使用     三、通过JSON或者YMAL文件配置logging模块 ====...

36612

扫码关注云+社区

领取腾讯云代金券