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加载顺序
- 容器读取<context-param></context-param>节点,并创建一个ServletContext实例,以节点的name作为键,value作为值,存储到上下文环境中。
- 容器读取<listener></listener>节点,根据配置的class类路径来创建监听。
- 容器读取<filter></filter>节点,根据配置路径实例化过滤器。
- 容器读取<servlet></servlet>节点,初始化servlet。
2.2 Spring配置文件的加载
众所周知,applicationContext.xml是Spring的配置文件,此文件的加载方式是通过context-param和ContextLoaderListener来加载的。
简单来说就是通过将配置文件路径写在contextConfigLocation里,然后让ContextLoaderListener获取并加载配置到上下文中。
2.3 MCC以及普通配置文件的加载
其实Java EE标准既然已定,那么各个框架、各种服务实现配置文件加载的机制也就大体相同。
因此,参考Spring加载配置的做法,我们可以在web.xml文件中发现另外一个具有美团烙印的Listener——MtDefaultContextListener。
我们只需要跟进他的contextInitialized方法看一下,就可以知道其是如何加载配置的了。
2.3.1 MtDefaultContextListener
通过分析代码,可以发现,MtDefaultContextListener做的工作主要有
- 初始化配置,包括系统环境变量、配置文件、MCC配置
- 初始化hlb
在初始化过程中,我们主要关注initConfigUtilAdapter这个方法。
2.3.2 initConfigUtilAdapter
跟进initConfigUtilAdapter方法,发现配置加载分为三类。
- 系统环境变量
- 配置文件
- MCC配置
initConfigUtilAdapter方法的作用主要就是将配置放置到ConfigurationManager.instance这个静态变量中
2.3.3 ConfigUtilAdapterRegister
Spring提供了一种加载配置文件的机制(applicationContext本身是如何加载的不再赘述),PropertyPlaceholderConfigurer,只需要在Spring配置文件中配置就可以指定配置文件路径加载。
美团组件通过继承PropertyPlaceholderConfigurer并重写loadProperties方法的方式,将ConfigurationManager.instance中的所有配置加载到Spring容器中。
完成这个工作的就是ConfigUtilAdapterRegister。
2.3.4 如何保证MtDefaultContextListener先于Spring加载配置到ConfigurationManager.instance
由web.xml来保证
之前提到过,Spring加载配置文件是由ContextLoaderListener完成的。
web.xml中配置的listener是顺序加载的。因此MtDefaultContextListener需要配置在ContextLoaderListener前面。
如下代码配置。
3.流程草图
4.参考文档
使用到到的第三方框架:Commons Configuration & Archaius
5.直接使用Commons Configutation和Archaius的Demo
5.1初始化
5.2获取配置
作者简介
崔宝森,16年加入美团点评,对技术有执着追求的90后文艺青年。博客地址:http://coderec.cn/