从零搭建并分析springboot(三)

147行ApplicationArguments applicationArguments = new DefaultApplicationArguments(args),入参的args被包装成DefaultApplicationArguments对象,应该是为了方便后续调用,也就是args参数目前用作了两种用途,一种是传递给监听事件,一种是包装成该对象

148行ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments),创建ConfigurableEnvironment对象,首先简单了解一下ConfigurableEnvironment接口是用来干嘛的,它继承了Environment接口,用来表示整个应用运行时的环境,Environment在容器中是一个抽象的集合,是指应用环境的2个方面:profiles和properties。准备这个对象用来干什么,暂时未知 Q5?

debug跟一下prepareEnvironment方法

prepareEnvironment方法

首先是getOrCreateEnvironment方法,默认创建StandardServletEnvironment对象,看一下默认得到的对象

得到的默认environment对象的一些属性

在这不深入研究这些属性

简单看一下然后做些猜测

propertyResolver里的东西,看起来挺像spring的@Value注解读取配置文件配置的字符,比如@Value("${name:'aaa'}") 该注解表示获取配置文件中的name,如果没配置,默认aaa

propertySources里的东西,应该就是获取到的配置文件,比如name='systemProperties'和name='systemEnvironment'这两个,是获取了java.lang.System系统属性和环境配置,另外两个servletConfigInitParams和servletContextInitParams,因为创建的是StandardServletEnvironment,所以这两个值应该跟servlet有关

这里仅做一些猜测,如果后续正好研究到,再深入分析

接下来执行configureEnvironment方法

configureEnvironment方法

conversionService,顾名思义,转换器,应该是从配置文件的配置转换为不同类型属性时用到

configurePropertySources,配置属性来源,上面已经看到默认的有4个,这里是配置其它来源的属性

configurePropertySources方法

通过SpringApplication对象的defaultProperties属性配置,该属性一般为空

通过启动类的入参配置,这里介绍一下这个入参,如果对打jar包后启动的命令使用过的话,应该了解过可以通过命令去手动做一些配置,比如java -jar xxx.jar --name=zhangsan 这样去配置参数,演示一下

添加入参
添加入参后启动效果

该配置放入了environment里,最后也能通过@Value得到,而且会覆盖application.yml里对应的同名配置

configureProfiles,配置profile(不知道怎么翻译,直接上代码)

configureProfiles方法

运行到这里时,由于还没开始加载classpath下的yml文件,所以需要的配置spring.profiles.active如果在文件里配置了,这个阶段走进这个方法,还是为null的,如果需要此时就能得到想加载的配置文件,可以通过命令java -jar xxx.jar --spring.profiles.active=test,这样启动会在这个阶段就生效

然后执行listeners.environmentPrepared((ConfigurableEnvironment)environment),在上一章有说过listeners.starting方法的作用,查看源码不难发现它跟starting差不多,也是发送监听事件,这次监听器ConfigFileApplicationListener加载了classpath下的配置文件进environment,具体怎么加载的这里就不研究了

接下来执行this.bindToSpringApplication((ConfigurableEnvironment)environment),该方法提取spring.main开头的配置绑定到SpringApplication对象上,比如配置spring.main.headless

到这也差不多完成了生成environment对象的工作,包括了创建默认SERVLET环境对象(其它的如StandardReactiveWebEnvironment、StandardEnvironment大体应该差不多),配置转换器、配置其它属性来源、配置active profile,发送事件到监听器ConfigFileApplicationListener读取classpath下配置文件,把environment对象里已读取到的属性前缀为spring.main的相关配置绑定回SpringApplication对象上。spring的Environment和Binder后续可以深入研究一下

把run方法的源码重新截图一下

重新贴的run源码

149行,configureIgnoreBeanInfo方法,该方法默认配置键为spring.beaninfo.ignore,值为true的property给java.lang.System,具体作用不重点分析了,有缘再说

150行,打印banner,即

springboot默认banner

可以更换打印内容,跟踪源码可以知道如何更换,这里只作其中一种方式的演示

定义spring.banner.location

在定义的文件夹路径下创建对应的文件

创建banner.txt

启动后打印如图

自定义的banner打印效果

151行,开始创建ApplicationContext对象

进入方法可以看到默认创建了AnnotationConfigServletWebServerApplicationContext对象,看一下类结构图

AnnotationConfigServletWebServerApplicationContext结构图

目前我们接触并分析到的有ApplicationContext,它是spring容器,装了各种各样的东西,另外还有一个EnvironmentCapable,实现类需要实现它的getEnvironment方法,environment也就是前面分析到的那些,跟踪源码会发现AnnotationConfigServletWebServerApplicationContext构造方法还会默认初始化一个(在父类构造方法中),这个初始化是为了生成AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象,这两个对象的作用后面再看,Q6?

这里来实践一个demo,也就是模拟ApplicationContext接口和EnvironmentCapable接口,做个简化版的出来便于理解

模仿LifeCycle接口,控制生命周期
模仿Environment接口,可获取属性
模仿EnvironmentCapable接口,可获取环境对象
模仿BeanFactory接口,有getBean方法
模仿ApplicationContext接口,作为容器,它装有运行的环境,所有的Bean对象,可控制的生命周期
CustomBeanFactory简单实现类,实现getBean方法,提供addBean方法装入Bean对象
CustomEnvironment简单实现类1
CustomEnvironment简单实现类2

写两个的原因是想描述spring不同的容器可能会加载不同的环境对象出来,从之前的分析中可以知道environment中放了很多属性,包括从配置文件中读取出来的,这里仅作最简单的处理(知道有这些途径就行)

CustomApplicationContext简单实现抽象类part1
CustomApplicationContext简单实现抽象类part2
CustomApplicationContext简单实现1,加载环境CustomSimple1Environment
CustomApplicationContext简单实现2,加载环境CustomSimple2Environment
测试两个容器,可以看到加载了不同的环境

接下来152行,这一行暂时从字面意思理解了,异常上报,从源码包中spring.factories也可以看到SpringBootExceptionReporter默认指定实现类FailureAnalyzers,应该能通过它分析并解决异常,Q7?

到目前问题总结

Q1 启动类run方法的两个入参,已经知道第一个参数用于创建SpringApplication对象,args用于监听事件传递参数(监听事件中具体用来干嘛应该不需要研究,springboot会有很多默认处理机制),args另一方面用于构建Environment,可以通过启动项目时添加相应的参数进Environment,然后应用于整个项目

Q2 ConfigurableApplicationContext如何创建对象并启动的,默认创建AnnotationConfigServletWebServerApplicationContext对象,通过一个简单demo描述了一下ApplicationContext是如何装载环境和bean的,spring中也是选择ApplicationContext的一个实现类通过构造方法创建对象,后面分析在springboot中是怎么启动的

Q3 java.lang.System中的prop对象赋key为java.awt.headless的值,作用未知

Q4 SpringApplicationRunListeners listeners对象目前分析了它的starting和environmentPrepared方法,最终发送事件给各启动监听,完整作用待分析,environmentPrepared时会加载classpath下的配置文件进environment

Q5 ConfigurableEnvironment的作用,就是加载各种运行时的环境配置,从系统System配置到配置文件的配置再到启动项目时的入参配置等,最终这些配置会加载进容器,被容器管理的bean可以使用这些配置

Q6 AnnotationConfigServletWebServerApplicationContext生成的AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner对象,作用未知

Q7 异常上报的作用,待分析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容