Spring多个PropertyPlaceholderConfigurer文件和数据库

时间:2014-08-25 16:44:28

标签: java spring javabeans

我想从使用Spring Beans的java应用程序加载属性,通过数据库,但是我需要从文件加载到数据库的连接属性。

所以我想要的是以下内容:

  1. 加载文件db.Properties
  2. 初始化DataSources的bean
  3. 加载剩余属性Base
  4. 最后,可以从两个来源访问已加载的属性。

    我尝试了以下方式。

    应用context.xml中:

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
    <!-- ************************************* -->
    <!--        1:  Files Properties Load      -->
    <!-- ************************************* -->
    <bean id="placeholderPropertiesFile" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>file:./properties/dataBase.properties</value>
                <value>file:./properties/webServicesUserPass.properties</value>
            </list>
        </property>
        <property name="placeholderPrefix" value="$file{" />
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="order" value="0" />
    </bean>
    
    
    
    <!-- ************************************* -->
    <!--        2:  Data Sources Load          -->
    <!-- ************************************* -->  
    
    <bean id="dataSourceOracleRead" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="$file{db.driverClassName}" />
        <property name="url" value="$file{dbRead.url}" />
        <property name="username" value="$file{dbRead.username}" />
        <property name="password" value="$file{dbRead.password}" />
        <property name="poolPreparedStatements" value="true" />
    </bean>
    
    <bean id="dataSourceOracleWrite" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="$file{db.driverClassName}" />
        <property name="url" value="$file{dbWrite.url}" />
        <property name="username" value="$file{dbWrite.username}" />
        <property name="password" value="$file{dbWrite.password}" />
        <property name="poolPreparedStatements" value="true" />
    </bean>
    
    
    <!-- ************************************* -->
    <!--        3:  Database Properties Load   -->
    <!-- ************************************* -->
    <bean id="placeholderPropertiesDatabase" class="xxx.xxx.DbPropertyPlaceholderConfigurer" >
        <property name="dt" ref="dataSourceOracleRead" />
        <property name="table" value="CONFIG0" />
        <property name="key" value="I_CODIGO" />
        <property name="value" value="C_VALOR" />
    
        <property name="placeholderPrefix" value="$db{" />
        <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
        <property name="ignoreUnresolvablePlaceholders" value="false" />
        <property name="order" value="1" />
    </bean>
    

    DbPropertyPlaceholderConfigurer:

    public class DbPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
        private DataSource dt;
    private String key;
    private String value;
    private String table;
    
    @Override
    protected void loadProperties(final Properties props) throws IOException {
        if (null == props) {
            throw new IOException("No properties passed by Spring framework - cannot proceed.");
        }
    
        String sql = String.format("SELECT %s, %s FROM %s", key, value, table);
    
        try {
            JdbcTemplate t = new JdbcTemplate(dt);
            t.query(sql, new RowCallbackHandler() {
                @Override
                public void processRow(ResultSet rs) throws SQLException {
                    String auxKey = rs.getString(key);
                    String auxValue = rs.getString(value);
    
                    if (null == auxKey || null == auxValue) {
                        throw new SQLException("Configuration database contains empty data. Name='" + (auxKey == null ? "" : auxKey)
                                + "', Value='" + (auxValue == null ? "" : auxValue) + "'.");
                    }
    
                    props.setProperty(auxKey, auxValue);
                }
            });
        } catch (Exception e) {
            logger.fatal("There is an error in either 'application.properties' or the configuration database.");
            throw new IOException(e);
        }
    
        if (props.size() == 0) {
            logger.fatal("The configuration database could not be reached or does not contain any properties in '" + table
                    + "'.");
        } else {
            logger.info("Application config info loaded from configuration database.");
        }
    }
    
    public void setDt(DataSource dt) {
        this.dt = dt;
    }
    
    public void setKey(String key) {
    this.key = key;
    }
    
    public void setValue(String value) {
    this.value = value;
    }
    
    public void setTable(String table) {
    this.table = table;
    }
    }
    

    错误:

    Exception in thread "Main Thread" org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.IOException: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '$file{db.driverClassName}'
        at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:661)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
        at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:84)
        at xxx.xxx.xxx.BatchMain.main(BatchMain.java:35)
    Caused by: java.io.IOException: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '$file{db.driverClassName}'
        at xxx.xxx.xxx.xxx.propertiesLoader.DbPropertyPlaceholderConfigurer.loadProperties(DbPropertyPlaceholderConfigurer.java:60)
        at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.java:161)
        at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:78)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:664)
        ... 4 more
    

    如果我选择初始化bean&#34; dataSourceOracleRead&#34;在application-context.xml中,访问数据库工作正常,而不是通过文件。

    <bean id="dataSourceOracleRead" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
    <property name="url" value="jdbc:oracle:thin:@10.10.10.10:1521:bdtest" />
    <property name="username" value="test" />
    <property name="password" value="qwerty" />
    <property name="poolPreparedStatements" value="true" />
    </bean>
    

    我想当我设置第二个&#34; PropertyPlaceholderConfigurer&#34;我通过第一个(属性文件)自动丢失已经收费的属性。

    如果我有两个&#34; PropertyPlaceholderConfigurer&#34;其中一个加载其中一个文件,第二个加载第二个文件,我不会通过第一个&#34; PropertyPlaceholderConfigurer&#34;来丢失收费属性。

    Ps:我使用的是弹簧版本3.1.2

1 个答案:

答案 0 :(得分:0)

如果您使用的是Spring 3.1,请考虑使用PropertySourcePlaceholderConfigurer,它与ConfigurableEnvironment结合使用,可以动态添加PropertySources

这样,您只能定义一个placeholderConfigurer,从属性文件初始化,然后从数据库加载其他属性。

另外,请检查其他question,它看起来与您想要的非常相似但使用不同的方法。