10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理( 二 )


这个源码分析也很简单,debug走一遍源码5分钟也就到了我们今天说的这个组件了,入口当然是我们的main函数了,我们只要看SpringApplication的源码基本上就了解了

10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
 
我们先打开SpringApplication#run方法
step1:我们第一个要关注的就是spring boot首先初始化了一个全局的事件监听器,这个事件监听器会伴随着springboot的整个生命周期,这个我们以后也会多次接触这个组件
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
初始化全局的事件监听器EventPublishingRunListener
step2:接下来就是开始准备springboot所有配置文件存储的仓库Environment,这个其实也很好理解,spring是管理bean的,bean里面也有很多属性,所以优先收集整个上下文的配置属性信息,将其放在一个篮子(Environment)里面,然后以后想要什么,就从篮子里面去获取,而不是在想要的时候,在去想办法获取,这样会导致整个springboot的代码变得不是很优雅
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
 
step3:我们进入prepareEnvironment方法
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
 
我们可以看到首先先调用getOrCreateEnvironment创建好一个"篮子",有了这个"篮子"我们才可以在这个"篮子"里面放我们想要的东西,所以我们可以接着看下一行的#configureEnvironment方法,例如System.setProperties之类信息会在这边进行加载,放到篮子里面
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
 
主要是加载如下的配置文件,你不要小看这样的配置文件,运维很有用,运维启动启动一般会配置启动参数,其实也就是在这个地方,启动参数被会spring boot解析到作为默认选项,加载到上下文中,作为启动的核心参数启动,但是一般这些参数叫做默认参数,优先级是最低的,如果你在代码有同key值的时候,就会覆盖运维配置的系统级变量值,这点我们平时开发的时候要注意,如下图所示,这点很重要,不过不是我们今天的重点
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
 
其实就算大家不看spring的源码,但是也知道spring有一个很牛的源码原则就是"开闭原则","篮子"是spring自己造的,东西也是spring自己放的,不能让我们这些使用者没有一点机会去做点什么,肯定不是springboot的风格,所以spring就开了一个口子,简单地说就是开了一个后门,貌似在说:我东西放完了,你有什么东西要放的啊,口子就在如下的代码中
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
 
我们可以看到方法名叫做environmentPrepared,调用者是listener,是一个监听器,也就是我们上文说的EventPublishingRunListener监听器,就是像是在说:"同志们,篮子我已经弄好了,你们有啥东西想放的赶紧放,放完我准备开始用了"
最后我们跟着源码debug,会到了ConfigFileApplicationListener的监听器实例,它监听的是一个ApplicationEnvironmentPreparedEvent,故其名曰"应用环境准备好事件",虽然有点绕口,也不通顺,但是看到这边我们就动了,springboot是靠一种事件订阅的方式来做解耦合的,源码如下
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
ConfigFileApplicationListener.JAVA
debug到现在,我们进入onApplicationEnvironmentPreparedEvent这个方法,就可以看到我们今天的主角的影子了,有请我们的主角登场
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图
EnvironmentPostProcessor初次出现
我们可以看到当loadPostProcessors执行完之后,看方法名我们也是是加载当前项目中EnvironmentPostProcessor,然后排序,最后调用我们刚刚说的postProcessorEnvironment方法,这个方法的具体实现,也就是我们上文实战小节的那个BazingaJSONEnvironmentPostProcessor的具体实践了,到现在为止,我们已经跟踪源码知道整个加载的主流程了
现在还剩下最后一个问题,为啥我们要写META-INF的spring.factorie配置文件了,答案就是在loadPostProcessors中了,这个方法是一个静态方法,调用SpringFactoriesLoader的loadFactories方法
10分钟搞懂SpringBoot的组件EnvironmentPostProcessor使用和原理

文章插图


推荐阅读