spring中使用的${} 以及@Value 注解的占位符,都在是spring容器初始化bean前,通过反射及类型转化把 占位符上的值转化为真实的值。
主要使用了 PropertySource、 PropertySources、PropertyResolver(PropertySourcesPropertyResolver)、PropertiesLoaderSupport(PropertySourcesPlaceholderConfigurer)类。
1、PropertySource
这个是org.springframework.core.env. PropertySource 抽象类,不是org.springframework.context.annotation.PropertySource注解哈。这个基类用来存key/value 键值对的,像Map、Properties类型的。
首先说下,这两个静态变量,因为定义为final 类型的 必须在构造方法中赋值。
这里的name 和 PropertSource 是有对应关系的,我们看下PropertySource 重写的equeals方法:
只要两个PropertSource 类的name值一样,那么就认为这是两个相同的PropertSource 对象。这就像我们使用@ PropertSource 注解在加载文件时,name就相当于被加载.prop文件的全路径名,如果两个文件名一样,那么就认为对应文件的内容是一样的。
在说这里的PropertSource<T> 抽象类,可以传入一个泛型的对象,这个对象用来处理这个抽象类的抽象方法:
/**
* Return the value associated with the given name,
* or {@code null} if not found.
* @param name the property to find
* @see PropertyResolver#getRequiredProperty(String)
*/
public abstract Object getProperty(String name);
像 MapPropertySource 类 传入 Map<String, Object> 对象,从而在getProperty方法里通过source.get(key) 的方式实现这个方法。
像PropertySourcesPlaceholderConfigurer类的postProcessBeanFactory方法中 通过传入Environment 类型的对象 ,通过Environment对象的source.getProperty(key)
方式实现这个方法。
2、PropertySources
package org.springframework.core.env;
/**
* Holder containing one or more {@link PropertySource} objects.
*
* @author Chris Beams
* @since 3.1
*/
public interface PropertySources extends Iterable<PropertySource<?>> {
/**
* Return whether a property source with the given name is contained.
* @param name the {@linkplain PropertySource#getName() name of the property source} to find
*/
boolean contains(String name);
/**
* Return the property source with the given name, {@code null} if not found.
* @param name the {@linkplain PropertySource#getName() name of the property source} to find
*/
PropertySource<?> get(String name);
}
这接口相当于PropertySource 的集合类,为PropertySource 服务的。</