使用PropertySourcesPlaceholderConfigurer

时间:2015-05-06 22:30:32

标签: java spring properties jasypt

我有一个包含jdbc.password={enc}laksksjdjdj

等值的属性文件

使用JDK 1.7和Spring 4.1.5,我的配置类看起来像这样

@PropertySources({
    @PropertySource("classpath:application.properties"),
    @PropertySource("classpath:env.properties")
})
@ComponentScan("com.acme")
@Configuration
public class SpringConfig
{
    @Autowired
    private ConfigurableEnvironment env;    

    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
    {
        return new EncryptedPropertySourcesPlaceholderConfigurer();
    }
}

我想要实现的是将属性文件中的任何值从加密值转换为实际值。有些值会被加密,有些则不会被加密。这是我到目前为止所尝试的,当我在convertProperties()上放置断点时,props参数始终为空。我无法理解这一点,因为我可以看到此时this.environment已加载文件中的所有属性。

public class EncryptedPropertySourcesPlaceholderConfigurer extends PropertySourcesPlaceholderConfigurer
{
    @Override 
    protected void convertProperties(Properties props)
    {
        Enumeration<?> propertyNames = props.propertyNames();

        while (propertyNames.hasMoreElements()) {

            String propertyName = (String) propertyNames.nextElement(); 
            String propertyValue = props.getProperty(propertyName); 

            // String convertedValue = <translate the value>;

            props.setProperty(propertyName, convertedValue);
        } 
    }

    @Override
    protected Properties mergeProperties() throws IOException {
        final Properties mergedProperties = super.mergeProperties();
        convertProperties(mergedProperties);
        return mergedProperties;
    }
}

是否有人能够使用PropertySourcesPlaceholderConfigurer实现这一目标?我在使用PropertyPlaceholderConfigurer的旧应用程序中使用了类似的逻辑,但是想使用更新的Spring配置。

我注意到Jasypt有类似的EncryptablePropertySourcesPlaceholderConfigurer,但这种行为方式相同,所以我很困惑。

2 个答案:

答案 0 :(得分:2)

由于某些原因,使用@PropertySources注释不能按预期工作。

调用EncryptedPropertySourcesPlaceholderConfigurer.convertProperties()时,自动装配的ConfigurableEnvironment不包含我的属性文件中的条目。根本没有对我列出的属性文件的引用。

为了解决这个限制,我删除了注释并在config类中显式加载了这些资源。所以现在看起来像这样

@ComponentScan("com.acme")
@Configuration
public class SpringConfig
{ 
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer()
    {
        EncryptedPropertySourcesPlaceholderConfigurer p = new EncryptedPropertySourcesPlaceholderConfigurer(new KeyfileDecryptor());
        p.setLocations(
                new ClassPathResource("application.properties"),
                new ClassPathResource("env.properties")
                );
        return p;
    }

    @Bean
    public DataSource dataSource(
            @Value("${jdbc.driverclassname}") String driverclassname,
            @Value("${jdbc.url}") String url,
            @Value("${jdbc.username}") String username,
            @Value("${jdbc.password}") String password)
    {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();

        dataSource.setDriverClassName(driverclassname);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        return dataSource;
    }
}

此更改引入了自动装配的ConfigurableEnvironment将为null的问题,因此我必须更改为使用@Value注入才能从属性中配置dataSource

现在一切都按预期工作,EncryptedPropertySourcesPlaceholderConfigurer.convertProperties()从两个文件中接收所有属性值。

答案 1 :(得分:-1)

编写了一个示例应用程序来添加对此处使用加密值的支持

https://github.com/pushpendra-jain/spring-examples/tree/master/PropertySourcesPlaceholderEncrypter

基本上,它没有尝试调用其convertProperty方法,而是覆盖了processProperties方法并完成了工作,并且代码肯定不会更改任何现有行为。

有关步骤,请参见https://github.com/pushpendra-jain/spring-examples/blob/master/README.md