Spring基础:Properties源码分析

615 阅读2分钟

Spring Version:4.3.6.RELEASE
spring-context:PropertySourcesPlaceholderConfigurer.class

1. PropertySourcesPlaceholderConfigurer类

PropertySourcesPlaceholderConfigurer通过现实BeanFactoryPostProcessor类的postProcessBeanFactory(ConfigurableListableBeanFactory)方法,在spring的生命周期中开始执行properties资源文件的加载。

1.1 PropertySourcesPlaceholderConfigurer加载properties的流程

第78行 - propertySources用于存储properties资源

private MutablePropertySources propertySources;

第125行 - 如果在声明该类时设置了propertySources的值,则不会再加载locations设置的资源和系统资源

if (this.propertySources == null) {
    this.propertySources = new MutablePropertySources();
    // 加载locations资源和environment资源
    // ......省略......
}

第153行 - appliedPropertySources对象是存储Properties资源的引用,可以使用getProperty(String)等方法获取propteris资源中的键值对。经过第125行至第152行对this.propertySources的处理逻辑,最终在第153行将其赋值给this.appliedPropertySources

this.appliedPropertySources = this.propertySources;

1.2 下图是PropertySourcesPlaceholderConfigurer类的UML类图
PropertySourcesPlaceholderConfigurer类图

  • PropertySourcesPlaceholderConfigurer类通过继承EnvironmentAware,将Environment对象注入到PropertySourcesPlaceholderConfigurer中。
  • PropertyResourceConfigurer类通过继承BeanFactoryPostProcessor,得到生命周期的执行阶段postProcessBeanFactory()方法。

1.3 PropertySourcesPlaceholderConfigurer主要方法的执行时序图
PropertySourcesPlaceholderConfigurer类的时序图

第一步,postProcessBeanFactory()方法

  • 第127-136行执行了加载environment资源的逻辑
  • 第138、139行执行了加载locations资源地址中的资源的逻辑,使用父类PropertiesLoaderSupport的mergeProperties()方法
  • 第140行根据localOverride的值判断加载的locations的资源是否覆盖加载的environment的资源

第二步,processProperties()方法

  • 第167-177行定义了StringValueResolver对象,这个对象是Spring在DefaultListableBeanFactory类中,第1072行实现${***}注入功能时使用的核心键值对象。
    public Object doResolveDependency(DependencyDescriptor descriptor, 
                                      String beanName,
                                      Set<String> autowiredBeanNames, 
                                      TypeConverter typeConverter) throws BeansException {
        // ......省略......
        Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
        if (value != null) {
            if (value instanceof String) {
                //第1086行,根据${***}中的键获取propteries资源中的值
                String strVal = resolveEmbeddedValue((String) value);
                // ......省略......
            }
            // ......省略......
        }
        // ......省略......
    }
    
  • 第180行,调用父类PlaceholderConfigurerSupport的doProcessProperties()方法

第三步,doProcessProperties()方法

  • 第211-226行执行验证逻辑
  • 第232行,将valueResolver对象传入到AbstractBeanFactory类的embeddedValueResolvers对象,用于第二步中DefaultListableBeanFactory类实现${***}功能。