Spring静态配置加载原理剖析

一、何为静态配置

应用配置大致可以分为两类:动态配置和静态配置。

动态配置:常用zookeeper存储,未预定义在应用中,具体值在运动时动态获取。

静态配置:预定义于应用中的*.properties文件,在Spring容器启动时解析k-v对,并注入到相应的${...}占位符中。


二、核心类模型

Spring静态配置加载原理剖析


三、主要流程解析

Spring静态配置加载原理剖析

PlaceholderConfigurerSupport的实现类:PropertyPlaceholderConfigurer和PropertySourcesPlaceholderConfigurer。

以PropertyPlaceholderConfigurer为例,具体解析流程如下:

Spring静态配置加载原理剖析

  • PropertiesLoaderSupport.mergeProperties():根据localOverride决定同名配置的覆写策略,合并xml文件中使用<prop>及<locations>标签定义的配置对,返回Properties对象。
  • PropertyResourceConfigurer.convertProperties():Spring提供的一个扩展点,可对上一步得到的Properties对象的k-v对进行自定义转换,默认不做转换直接返回原始Properties对象。借助此扩展点可以实现配置加解密,如将敏感配置定义为encrypted_key=value(value为加密的敏感信息),当扫描到propertyName有"encrypted_"前缀时,对value进行解密。
  • PropertyPlaceholderConfigurer.processProperties():

a.创建PlaceholderResolvingStringValueResolver实例,用于bean占位符解析;

b.调用PlaceholderConfigurerSupport.doProcessProperties()方法,传入a步骤得到的解析器:

借助解析器,在BeanDefinitionVisitor.visitBeanDefinition()尝试访问bean的详细信息。这里我们只关注bean的property替换,直接找到BeanDefinitionVisitor.visitPropertyValues()方法。继续追到BeanDefinitionVisitor.resolveStringValue()方法,终于调到了我们的解析器PlaceholderResolvingStringValueResolver.resolveStringValue()。具体的解析工作交由PropertyPlaceholderHelper.replacePlaceholders(),有兴趣可以研究一下这段代码,Spring对于bean配置值的嵌套占位符支持也是在这里体现的(如:${...${...}})。

总之,这一步做的就是访问当前BeanFactory实例中的所有bean定义信息,若有使用占位符(如:key=${...}),则尝试在前面得到的Properties对象中查找相应的k-v对做替换(如:key=value),用value完善bean定义信息。