How to configure a Spring beans with properties th

2019-01-21 14:20发布

问题:

In my project we'd like to externalize the properties of our Spring managed beans, that is very easy to do with standard Java .properties files, however we want to be able to read those properties from a DB table that behaves like a Map (key is the property name, value is the value assigned to that property).

I found this post that suggest the usage of Commons Configuration but I don't know if there's a better way to do the same with Spring 3.x. Maybe implementing my own PropertyResource or something.

Any clues?

回答1:

I'd use a FactoryBean of type <Properties> that I'd implement using JdbcTemplate. You can then use the generated Properties object with the <context:property-placeholder> mechanism.

Sample code:

public class JdbcPropertiesFactoryBean
    extends AbstractFactoryBean<Properties>{

    @Required
    public void setJdbcTemplate(final JdbcTemplate jdbcTemplate){
        this.jdbcTemplate = jdbcTemplate;
    }
    private JdbcTemplate jdbcTemplate;

    @Required
    public void setTableName(final String tableName){
        this.tableName = tableName;
    }
    private String tableName;

    @Required
    public void setKeyColumn(final String keyColumn){
        this.keyColumn = keyColumn;
    }
    private String keyColumn;

    @Required
    public void setValueColumn(final String valueColumn){
        this.valueColumn = valueColumn;
    }
    private String valueColumn;

    @Override
    public Class<?> getObjectType(){
        return Properties.class;
    }

    @Override
    protected Properties createInstance() throws Exception{
        final Properties props = new Properties();
        jdbcTemplate.query("Select " + keyColumn + ", " + valueColumn
            + " from " + tableName, new RowCallbackHandler(){

            @Override
            public void processRow(final ResultSet rs) throws SQLException{
                props.put(rs.getString(1), rs.getString(2));
            }

        });
        return props;
    }
}

XML Configuration:

<bean id="props" class="foo.bar.JdbcPropertiesFactoryBean">
    <property name="jdbcTemplate">
        <bean class="org.springframework.jdbc.core.JdbcTemplate">
            <!-- reference to a defined data source -->
            <constructor-arg ref="dataSource" />
        </bean>
    </property>
    <property name="tableName" value="TBL_PROPERTIES" />
    <property name="keyColumn" value="COL_KEY" />
    <property name="valueColumn" value="COL_VAL" />
</bean>

<context:property-placeholder properties-ref="props" />


回答2:

In addition to Sean's suggestion, you can extend PropertyPlaceholderConfigurer. Look at the two current implementations - PreferencesX and ServletContextX, and roll out your own, jdbc-based.



回答3:

There are ways to create "PropertyPlaceholderConfigurer" Programmatically , please see below.

Write a DAO which reads Properties and create a PropertyPlaceholderConfigurer as shown below.

XmlBeanFactory factory = new XmlBeanFactory(new FileSystemResource("beans.xml"));
PropertyPlaceholderConfigurer cfg = new PropertyPlaceholderConfigurer();
cfg.setProperties(yourProperties);
cfg.postProcessBeanFactory(factory);