1.疑惑

1.在通过脚手架搭建的大多数美团项目中,很少见到显式指定配置文件所在目录的。

2.一些没有在配置文件中定义的变量,在MCC中配置后,却可以在项目中直接使用。

以上两个问题,其实可以归纳为一个问题——这些项目是如何加载配置文件以及MCC中的配置的?

2.追查

2.1 Web.xml

web.xml,这个最容易被忽视的配置文件,其实是web项目的核心配置文件。

web项目的一切都是从这里开始。

context-param、listener、filter、servlet,一切的一切都在这里定义。因此,想研究web项目的配置加载过程,自然从这里开始。

2.1.1 Web.xml加载顺序


  1. 容器读取​<context-param></context-param>节点,并创建一个ServletContext实例,以节点的name作为键,value作为值,存储到上下文环境中。
  2. 容器读取<listener></listener>节点,根据配置的class类路径来创建监听。
  3. 容器读取<filter></filter>节点,根据配置路径实例化过滤器。
  4. 容器读取<servlet></servlet>节点,初始化servlet。

2.2 Spring配置文件的加载

众所周知,applicationContext.xml是Spring的配置文件,此文件的加载方式是通过context-param和ContextLoaderListener来加载的。

简单来说就是通过将配置文件路径写在contextConfigLocation里,然后让ContextLoaderListener获取并加载配置到上下文中。

【新美大组件】MtDefaultContextListener加载配置过程_配置文件

2.3 MCC以及普通配置文件的加载

其实Java EE标准既然已定,那么各个框架、各种服务实现配置文件加载的机制也就大体相同。

因此,参考Spring加载配置的做法,我们可以在web.xml文件中发现另外一个具有美团烙印的Listener——MtDefaultContextListener。

我们只需要跟进他的contextInitialized方法看一下,就可以知道其是如何加载配置的了。

2.3.1 MtDefaultContextListener

通过分析代码,可以发现,MtDefaultContextListener做的工作主要有


  1. 初始化配置,包括系统环境变量、配置文件、MCC配置
  2. 初始化hlb

在初始化过程中,我们主要关注initConfigUtilAdapter这个方法。

【新美大组件】MtDefaultContextListener加载配置过程_加载_02

2.3.2 initConfigUtilAdapter

跟进initConfigUtilAdapter方法,发现配置加载分为三类。


  1. 系统环境变量
  2. 配置文件
  3. MCC配置

initConfigUtilAdapter方法的作用主要就是将配置放置到ConfigurationManager.instance这个静态变量中

【新美大组件】MtDefaultContextListener加载配置过程_配置文件_03

【新美大组件】MtDefaultContextListener加载配置过程_配置文件_04

【新美大组件】MtDefaultContextListener加载配置过程_配置文件_05

2.3.3 ConfigUtilAdapterRegister

Spring提供了一种加载配置文件的机制(applicationContext本身是如何加载的不再赘述),PropertyPlaceholderConfigurer,只需要在Spring配置文件中配置就可以指定配置文件路径加载。

【新美大组件】MtDefaultContextListener加载配置过程_spring_06

美团组件通过继承PropertyPlaceholderConfigurer并重写loadProperties方法的方式,将ConfigurationManager.instance中的所有配置加载到Spring容器中。

完成这个工作的就是ConfigUtilAdapterRegister。

【新美大组件】MtDefaultContextListener加载配置过程_配置文件_07

【新美大组件】MtDefaultContextListener加载配置过程_加载_08

【新美大组件】MtDefaultContextListener加载配置过程_spring_09

2.3.4 如何保证MtDefaultContextListener先于Spring加载配置到ConfigurationManager.instance

由web.xml来保证

之前提到过,Spring加载配置文件是由ContextLoaderListener完成的。

web.xml中配置的listener是顺序加载的。因此MtDefaultContextListener需要配置在ContextLoaderListener前面。

如下代码配置。

【新美大组件】MtDefaultContextListener加载配置过程_spring_10

3.流程草图

【新美大组件】MtDefaultContextListener加载配置过程_spring_11

4.参考文档

使用到到的第三方框架:Commons Configuration & Archaius


5.直接使用Commons Configutation和Archaius的Demo

5.1初始化

【新美大组件】MtDefaultContextListener加载配置过程_加载_12

5.2获取配置

【新美大组件】MtDefaultContextListener加载配置过程_配置文件_13


作者简介

    ​崔宝森,16年加入美团点评,对技术有执着追求的90后文艺青年。博客地址:http://coderec.cn/