PropertyPlaceholderConfigurer 是个BeanFactoryPostProcessor实现,可以实现在XML配置文件中通过占位符,引入外部属性文件(properties文件)
PropertyPlaceholderConfigurer实现BeanFactoryPostProcessor源码:
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
try {
Properties mergedProps = this.mergeProperties();
this.convertProperties(mergedProps);
//在这里会给@Value注解的Bean的方法/属性,按property的配置赋值
this.processProperties(beanFactory, mergedProps);
} catch (IOException var3) {
throw new BeanInitializationException("Could not load properties", var3);
}
}
systemPropertiesMode属性:1.SYSTEM_PROPERTIES_MODE_FALLBACK模式:默认在指定的 properties 文件中找不到你需要的属性,它还会在 Java 的 System 类属性中查找。2.SYSTEM_PROPERTIES_MODE_NEVER模式:只允许在 properties 文件中查找,不允许去System类中查找。3.SYSTEM_PROPERTIES_MODE_OVERRIDE模式:优先 System 类中查找,找不到再去 properties 文件中查找,与默认模式正好相反。如果你想在System中设置变量配置,可以使用System.setProperty(key, value);但是不建议这样做。
location属性:可变参数,扫描配置文件的路径
processProperties/doProcessProperties方法:在这个方法里会根据当前环境下property文件生成PlaceholderResolvingStringValueResolver对象,在doProcessProperties方法中给使用@Value注解的Bean的方法/属性赋值,我们重写这个方法,就可以获取到当前环境下的property配置
自实现代码
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
public class PropertiesUtil extends PropertyPlaceholderConfigurer {
private static Map<String, String> propertiesMap;
private int springSystemPropertiesMode = PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK;
public PropertiesUtil() {
}
@Override
public void setSystemPropertiesMode(int systemPropertiesMode) {
super.setSystemPropertiesMode(systemPropertiesMode);
this.springSystemPropertiesMode = systemPropertiesMode;
}
@Override
protected void processProperties(ConfigurableListableBeanFactory beanFactory, Properties props) throws BeansException {
super.processProperties(beanFactory, props);
propertiesMap = new HashMap<>();
Iterator i = props.keySet().iterator();
while (i.hasNext()) {
Object key = i.next();
String keyStr = key.toString();
String valueStr = this.resolvePlaceholder(keyStr, props, this.springSystemPropertiesMode);
//在这里会给@Value注解的Bean的方法/属性,按property的配置赋值
propertiesMap.put(keyStr, valueStr);
}
}
public static String getProperty(String name) {
return propertiesMap.get(name);
}
}
在XML文件中配置自定义的PropertiesUtil,设置相关属性(主要是扫描配置文件的路径)
<!--你的自定义的PropertyPlaceholderConfigurer实现类-->
<bean class="com.my.project.util.PropertiesUtil">
<property name="locations">
<list>
<value>classpath:config.properties</value>
<value>classpath:database.properties</value>
</list>
</property>
</bean>
好了,我们可以在代码里使用它了,举个例子,比如我们关于kafka的topic配置在kafka.property中,线下环境kafka.property中kafka.topic=kafka_test,线上环境kafka.topic=kafka_prod。我们直接通过PropertiesUtil.getProperty("kafka.topic"),就可以获取到当前环境下的配置了