1.springAppication构造器

  基于getSpringFactoriesInstances方法构造如下类(获取文件内容在META-INF/spring.factories文件中)

  1.1 初始化ApplicationContextInitializer.class

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer

  1.2 初始化ApplicationListener.class

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

2.run方法

		StopWatch stopWatch = new StopWatch();//构造时间观察器
stopWatch.start();// 打印一个开始时间
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();// 配置headless 依据java.awt.headless
SpringApplicationRunListeners listeners = getRunListeners(args);// 解析如下
// getSpringFactoriesInstances方法获取SpringApplicationRunListener.class对象->EventPublishingRunListener对象
// EventPublishingRunListener对象初始化时,构造器内会执行下面的逻辑
//SimpleApplicationEventMulticaster广播器初始化,并且将listener设置到广播器中
// 将上面获取到的EventPublishingRunListener对象对象添加到SpringApplicationRunListeners对象中
listeners.starting(); // 解析如下
// 调用EventPublishingRunListener对象的starting方法
// 将ApplicationStartingEvent广播出去 SimpleApplicationEventMulticaster->multicastEvent方法
// 调用getApplicationListeners方法获取所有listeners,然后循环广播
// 调用支持事件的listener的listener.onApplicationEvent(event);方法,驱动listener巡行
// 此处支持的listener如下
// org.springframework.boot.logging.LoggingApplicationListener,
// org.springframework.boot.autoconfigure.BackgroundPreinitializer,
// org.springframework.boot.context.config.DelegatingApplicationListener,
// org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
// 创建一个DefaultApplicationArguments对象,构造器中构造了一个新的SOURCE对象
// 根据SOURCE对象的继承结构->SimpleCommandLinePropertySource->parse方法
// 如果args是–开头的,就加入OptionArg中,否则加入到NonOptionArg中
// CommandLinePropertySource构造其中commandLineArgs存入source
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// 参照下面的prepareEnvironment方法分析
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment); // 打印banner
context = createApplicationContext();
// 创建applicationContext
// 添加AnnotationTypeFilter–>Component 添加AnnotationTypeFilter –> ManagedBean 添加AnnotationTypeFilter –> javax.inject.Named
// exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 异常处理
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//
refreshContext(context);
//
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}

  

prepareEnvironment方法分析

private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 获取或者创建ConfigurableEnvironment 构造environment对象 继承AbstractEnvironment
// AbstractEnvironment构造器中调用customizePropertySources方法
// StandardEnvironment对象:配置systemEnvironment systemProperties
// StandardServletEnvironment对象:配置servletContextInitParams servletConfigInitParams jndiProperties
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 配置环境的信息
// configurePropertySources 配置PropertySources
// commandLineArgs、servletConfigInitParams、servletContextInitParams、jndiProperties(如果存在)、
// systemProperties、systemEnvironment、defaultProperties(如果存在)
// configureProfiles 配置Profiles
// 至于哪个具体的配置文件会被加载,需要在application.properties文件中通过spring.profiles.active属性来设置,其值对应{profile}值。
// application-dev.properties:开发环境 application-test.properties:测试环境 application-prod.properties:生产环境
listeners.environmentPrepared(environment);
// 通知所有的观察者,发送ApplicationEnvironmentPreparedEvent事件.
// org.springframework.boot.context.config.ConfigFileApplicationListener,
// org.springframework.boot.context.config.AnsiOutputApplicationListener,
// org.springframework.boot.logging.LoggingApplicationListener,
// org.springframework.boot.logging.ClasspathLoggingApplicationListener,
// org.springframework.boot.autoconfigure.BackgroundPreinitializer,
// org.springframework.boot.context.config.DelegatingApplicationListener,
// org.springframework.boot.context.FileEncodingApplicationListener
//
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}

  

prepareContext分析
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
// 1. 上下文设置环境
context.setEnvironment(environment);
// 2. 调用postProcessApplicationContext方法设置上下文的beanNameGenerator和resourceLoader(如果SpringApplication有的话)
postProcessApplicationContext(context);
// 3. 拿到之前实例化SpringApplication对象的时候设置的ApplicationContextInitializer,调用它们的initialize方法,对上下文做初始化
applyInitializers(context);
// 4. contextPrepareds 是一个空实现
listeners.contextPrepared(context);
// 5. 打印启动日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
} // Add boot specific singleton beans
// 6. 日志往上下文的beanFactory中注册一个singleton的bean,bean的名字是springApplicationArguments,bean的实例是之前实例化的ApplicationArguments对象
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
// 如果之前获取的printedBanner不为空,那么往上下文的beanFactory中注册一个singleton的bean,bean的名字是springBootBanner,bean的实例就是这个printedBanner
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
} // Load the sources
Set<Object> sources = getSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 7. 调用load方法注册启动类的bean定义,也就是调用SpringApplication.run(Application.class, args);的类,SpringApplication的load方法内会创建BeanDefinitionLoader的对象,并调用它的load()方法
load(context, sources.toArray(new Object[sources.size()]));
// 8. 调用listeners的contextLoaded方法,说明上下文已经加载,该方法先找到所有的ApplicationListener,遍历这些listener,如果该listener继承了ApplicationContextAware类,那么在这一步会调用它的setApplicationContext方法,设置context
listeners.contextLoaded(context);
}

  

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor

  

1.SpringFactoriesLoader类

  loadFactoryNames->loadSpringFactories->META-INF/spring.factories

  位置:spring-boot-2.0.5.RELEASE-sources.jar目录下

springboot 源码笔记的更多相关文章

  1. SpringBoot是如何实现自动配置的?--SpringBoot源码(四)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoot源码(三 ...

  2. 如何搭建自己的SpringBoot源码调试环境?--SpringBoot源码(一)

    1 前言 这是SpringBoot2.1源码分析专题的第一篇文章,主要讲如何来搭建我们的源码阅读调试环境.如果有经验的小伙伴们可以略过此篇文章. 2 环境安装要求 IntelliJ IDEA JDK1 ...

  3. SpringBoot内置的各种Starter是怎样构建的?--SpringBoot源码(六)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五) 温 ...

  4. SpringBoot的启动流程是怎样的?SpringBoot源码(七)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 SpringBoot内置的各种Starter是怎样构建的? SpringBoot源码(六) 温故而知新, ...

  5. SpringApplication对象是如何构建的? SpringBoot源码(八)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 本篇接 SpringBoot的启动流程是怎样的?SpringBoot源码(七) 1 温故而知新 温故而知新,我们来简单回顾一下上 ...

  6. SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...

  7. SpringBoot内置生命周期事件详解 SpringBoot源码(十)

    SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringBoot事件监听 ...

  8. Zepto源码笔记(一)

    最近在研究Zepto的源码,这是第一篇分析,欢迎大家继续关注,第一次写源码笔记,希望大家多指点指点,第一篇文章由于首次分析原因不会有太多干货,希望后面的文章能成为各位大大心目中的干货. Zepto是一 ...

  9. redis源码笔记(一) —— 从redis的启动到command的分发

    本作品采用知识共享署名 4.0 国际许可协议进行许可.转载联系作者并保留声明头部与原文链接https://luzeshu.com/blog/redis1 本博客同步在http://www.cnblog ...

随机推荐

  1. python 应用 base64、hmac、hashlib包实现:MD5编码 base64编码解码、SHA256编码、urlsafe_b64encode编码等等基本所有的加密签名的方法

    用python做HTTP接口自动化测试的时候,接口的很多参数是经过各种编码加密处理后在传到后台的,这里列举出python实现 应用 base64.hmac.hashlib包实现:md5编码 sha1编 ...

  2. char、varchar、nchar、nvarchar特点比较

    于程序中的string型字段,SQLServer中有char.varchar.nchar.nvarchar四种类型来对应(暂时不考虑text和ntext),开建立数据库中,对这四种类型往往比较模糊,这 ...

  3. SQL 取两日期的记录

    SELECT TOP 1000 [ID]      ,[SourcePageID]      ,[PlatformType]      ,[CreateTime]  FROM [home_sendor ...

  4. Angular6 学习笔记——内容投影, ViewChild和ContentChild

    angular6.x系列的学习笔记记录,仍在不断完善中,学习地址: https://www.angular.cn/guide/template-syntax http://www.ngfans.net ...

  5. SQL学习笔记1

    2018.10.15:周一   -- 返回前5个数据 SELECT TOP 5 * FROM Student;   -- 返回前50%的数据 SELECT TOP 50 PERCENT * FROM ...

  6. 数据库如何从SQL server转换到SQLite

    我之前用的是SQL server数据库,但是客户那里觉得安装这个大的数据库比较卡,说是导致蓝屏了,硬往SQL server上赖,没有办法客户是上帝么,给他换个小点的数据库吧!考虑Access,不行这个 ...

  7. 工信部公示网络安全示范项目 网易云易盾“自适应DDoS攻击深度检测和防御系统”入选

    本文由  网易云发布. 工信部官网 2017年年底,经专家评审和遴选,中华人民共和国工业和信息化部(以下简称“工信部”)公示了2017年电信和互联网行业网络安全试点示范项目,网易云易盾的“自适应DDo ...

  8. PHP之旅9 MySQL数据库

    PHP最主要的还是进行数据处理的,所以与数据库的交互是非常重要的. 现在主流的数据库有:Oracle.DB2.Microsoft SQL Server.MySQL等. MySQL由于其体积小.速度快. ...

  9. 恢复xfs文件系统superblock实验

    1. 创建一个XFS文件系统[root@localhost ~]# mkfs.xfs -f /dev/vdb1meta-data=/dev/vdb1              isize=256    ...

  10. 【洛谷P4934】 礼物,拓扑排序

    题目大意:给你$n$个不重复的数,其值域为$[0,2^k)$,问你至少需要将这$n$个数拆成多少个集合,使得它们互相不是对方的子集,并输出方案. 数据范围:$n≤10^6$,$k≤20$. $MD$我 ...