您的位置:

Property-placeholder详解

一、property-placeholderhelp

Property-placeholder是Spring框架提供的一种用于替换XML中属性占位符的机制。它可以读取Properties文件,并且在XML文件中取出相应的属性值,并将其替换为占位符,该机制对于模块化配置、测试、灵活性以及重用方面都具有很大的优势。

在Spring的应用上下文中,通过PropertyPlaceholderConfigurer可以很方便的读取Properties文件,并用${}的语法来引用读取的属性值,当然在引用值为空的时候,可以设置默认值。例如:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driverClassName}" />
    <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
</bean>

在上述的代码中,${jdbc.driverClassName}、${jdbc.url}、${jdbc.username} 和 ${jdbc.password} 都是PropertyPlaceholderConfigurer读取Properties文件中所定义的属性名。

二、property-placeholderhelper

除了通过PropertyPlaceholderConfigurer来读取Properties文件之外,Spring 4.3版本以后,还提供了一个更加强大的属性加载机制 -- PropertySourcesPlaceholderConfigurer。PropertySourcesPlaceholderConfigurer继承自PropertyPlaceholderConfigurer,并且更加灵活,支持从多个地方读取属性文件,包括系统属性、Java配置类、环境变量等等。实际上,它也是Spring @PropertySources注解使用的核心类。

在Java配置类中配置示例:

@Configuration
@ComponentScan
@PropertySources(value = {
        @PropertySource("classpath:application.properties"),
        @PropertySource("file:/opt/config/application.properties")
})
public class AppConfig {

    @Autowired
    Environment env;

    @Bean
    public DataSource dataSource() {
        BasicDataSource dataSource = new BasicDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.username"));
        dataSource.setPassword(env.getProperty("jdbc.password"));
        return dataSource;
    }

}

使用PropertySourcesPlaceholderConfigurer可以在Java配置类中从多个地方加载属性,并且与其他的Spring组件无缝集成。

三、property-placeholder热加载

在大多数情况下,我们不会在运行时更改属性文件中的值,但是,在一些特殊的情况下,我们可能需要热修改Properties文件的值,并且更新Spring容器中的Bean。Spring框架自身并没有提供热修改属性文件的功能,但是我们可以自己实现一个热加载的机制。

我们可以在程序中监控Properties文件的修改,并且在文件发生变更时,重新读取Properties文件,并且更新Spring中的Bean。示例代码如下:

@Configuration
@PropertySources(value = {@PropertySource("classpath:config.properties")})
public class AppConfig {

    @Autowired
    Environment env;

    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
        configurer.setLocation(new ClassPathResource("config.properties"));
        configurer.setIgnoreResourceNotFound(false);
        configurer.setIgnoreUnresolvablePlaceholders(false);
        configurer.setProperties(CommonUtils.loadProperties(configurer.getLocation()));
        return configurer;
    }

    /**
     * 监听文件修改
     */
    @PostConstruct
    public void init() {
        String location = env.getProperty("spring.config.location");
        if (location != null) {
            File file = new File(location);
            if (!file.exists()) {
                throw new FileNotFoundException("The config file does not exist: " + file.toString());
            }
            if (location.endsWith(".properties")) {
                new PropertiesFileListener(file, this::reloadProperties).watch();
            }
        }
    }

    /**
     * 重新加载Properties文件
     * @param properties Properties
     */
    public void reloadProperties(Properties properties) {
        PropertySourcesPlaceholderConfigurer configurer = propertySourcesPlaceholderConfigurer();
        configurer.setProperties(properties);
    }

    ..........
}

四、PropertyPlaceholderConfigurer

PropertyPlaceholderConfigurer是Spring框架中的一个核心组件,它是Properties文件中的属性值占位符解析器。它提供了多种方式来解析Properties文件中的占位符,例如,可以使用系统环境变量、标准JRE属性、命令行参数、JNDI等等方式。通过PropertyPlaceholderConfigurer,我们可以轻松地将XML配置文件和Properties文件进行解耦合,从而实现灵活性和可维护性。例如:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:config.properties</value>
        </list>
    </property>
</bean>

在上述代码中,我们将Properties文件的配置放置到了Spring的Application Context对象中,并且可以通过占位符来引用Properties文件中的参数。

五、结合注解使用

除了XML配置之外,Property-placeholder在注解中也得到了广泛的应用,Spring提供了@Value注解来读取Properties文件中的配置参数,用法如下:

@Value("${jdbc.driverClassName}")
private String driverClassName;

@Value("${jdbc.url}")
private String url;

@Value("${jdbc.username}")
private String username;

@Value("${jdbc.password}")
private String password;

使用@Value注解读取Properties文件中的配置参数,可以避免在Java代码中硬编码参数值,也可以让配置从不同的环境中进行分离。

总结

Property-placeholder机制在Spring框架中得到了广泛地应用,在不同的开发场景中起到了不可替代的作用。通过本文的介绍,我们知道,Spring提供了多种加载Properties文件的方式,从XML配置、Java配置到注解方式,我们可以根据实际的开发情况来选择使用哪种方式。同时,在热加载方面,我们需要根据实际需求进行调整,以达到最佳的实践效果。