Spring 加载 *.properties 文件的源码分析

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

Spring 是如何加载 *.properties 文件的?

1、属性加载器

PropertyPlaceholderConfigurer.java 类图结构
20191123100339\_1.png

通过类图,我们可以看到,PropertyPlaceholderConfigurer 实现了 BeanFactoryPostProcessor 接口,该接口中只有一个接口方法,通过方法注释我么可以了解到:
(1)、该接口可在 bean 实例化之前修改 Application Context ;
(2)、可以加载所有的bean定义,但是bean还没有并实例化;
(3)、允许通过对期待实例化的 Bean 属性进行覆盖和添加。
(4)、BeanFactoryPostProcessor 是一个特别的接口,当Spring加载任何实现了这个接口的bean的配置时,都会在工厂载入所有bean的配置之后执行 postProcessBeanFactory 方法。

    public interface BeanFactoryPostProcessor {

        /**
         * Modify the application context's internal bean factory after its standard
         * initialization. All bean definitions will have been loaded, but no beans
         * will have been instantiated yet. This allows for overriding or adding
         * properties even to eager-initializing beans.
         * @param beanFactory the bean factory used by the application context
         * @throws org.springframework.beans.BeansException in case of errors
         */
        void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

    }

2、属性资源加载器
(1)、PropertyResourceConfigurer # postProcessBeanFactory

    /**
     * {@linkplain #mergeProperties Merge}, {@linkplain #convertProperties convert} and
     * {@linkplain #processProperties process} properties against the given bean factory.
     * @throws BeanInitializationException if any properties cannot be loaded
     */
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        try {
            Properties mergedProps = mergeProperties();//加载配置文件到properties

            // Convert the merged properties, if necessary.
            convertProperties(mergedProps);  //必要则转换合并后的属性

            // Let the subclass process the properties.
            processProperties(beanFactory, mergedProps);// 子类初始这些属性,例如:PropertyPlaceholderConfigurer 
        }
        catch (IOException ex) {
            throw new BeanInitializationException("Could not load properties", ex);
        }
    }

(2)、PropertiesLoaderSupport # mergeProperties 完成属性文件的读取。
通过源代码分析我们可以看出来,如果 property 中的属性key存在重复的清苦,则后加载的会覆盖先加载的key值!!!
/**
* Return a merged Properties instance containing both the
* loaded properties and properties set on this FactoryBean.
*/
protected Properties mergeProperties() throws IOException {
Properties result = new Properties();

        if (this.localOverride) {
            // Load properties from file upfront, to let local properties override.
            loadProperties(result);
        }

        if (this.localProperties != null) {
            for (Properties localProp : this.localProperties) {// 多个属性文件循环读取,key 相同则覆盖
                CollectionUtils.mergePropertiesIntoMap(localProp, result);
            }
        }

        if (!this.localOverride) {
            // Load properties from file afterwards, to let those properties override.
            loadProperties(result);
        }

        return result;
    }

    /**
     * Load properties into the given instance.
     * @param props the Properties instance to load into
     * @throws IOException in case of I/O errors
     * @see #setLocations
     */
    protected void loadProperties(Properties props) throws IOException {
        if (this.locations != null) {
            for (Resource location : this.locations) {
                if (logger.isInfoEnabled()) {
                    logger.info("Loading properties file from " + location);
                }
                try {
                    PropertiesLoaderUtils.fillProperties(
                            props, new EncodedResource(location, this.fileEncoding), this.propertiesPersister);// 将配置文件中的属性读入到 props 中
                }
                catch (IOException ex) {
                    if (this.ignoreResourceNotFound) {
                        if (logger.isWarnEnabled()) {
                            logger.warn("Could not load properties from " + location + ": " + ex.getMessage());
                        }
                    }
                    else {
                        throw ex;
                    }
                }
            }
        }
    }

3、属性读取工具类
PropertiesLoaderUtils # fillProperties 通过IO读取资源文件。
20191123100339\_2.png

4、AbstractBeanFactory 解析占位符

AbstractBeanFactory # resolveEmbeddedValue

    public String resolveEmbeddedValue(String value) {
        String result = value;
        for (StringValueResolver resolver : this.embeddedValueResolvers) {
            if (result == null) {
                return null;
            }
            result = resolver.resolveStringValue(result);
        }
        return result;
    }

5、DefaultListableBeanFactory # resolveDependency 方法
  
20191123100339\_3.png

6、AutowiredAnnotationBeanPostProcessor 属性自动注入
 
20191123100339\_4.png

通过反射的方式将占位符的值得以替换。

以上即是整个 properties 文件从加载到替换属性的全过程。


来源:http://ddrv.cn/a/88268

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring 加载 *.properties 文件的源码分析

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏