2014-10-01 10 views
5

Ho una semplice applicazione in cui sto usando diversi file di proprietà per recuperare contenuti modificati da altri utenti (collegamenti a siti, ecc.).Come posso ricaricare il file delle proprietà nella primavera 4 usando le annotazioni?

La classe dove ho caricare le proprietà simile a questa:

@Configuration 
@PropertySource("classpath:salestipsWhitelist.properties") 
public class SalestipsWhitelist { 

@Autowired 
Environment env; 

public Environment getEnv() { 
    return env; 
} 

public void setEnv(Environment env) { 
    this.env = env; 
} 

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

Alcune delle proprietà del file:

UPS_MPP_M_L=True 
UPS_MPP_M_M=True 
UPS_MPP_M_MP=True 
UPS_MPP_M_S=True 

Questo funziona bene, ma se faccio modifiche delle proprietà del file, devo ricaricare l'app per visualizzare eventuali modifiche apportate.

È possibile, se si sposta il percorso su disco invece di classpath, per ricaricarlo periodicamente o manualmente? Non voglio che ciò avvenga automaticamente in caso di modifica, in quanto voglio avere il controllo quando questo viene fatto/aggiornato.

risposta

5

Questo funziona a meraviglia. Richiede Java 7, Apache Commons Logging, Apache Commons Lang (v2.6) e Apache Commons Configuration:

package corejava.reloadTest; 

import org.apache.commons.configuration.ConfigurationException; 
import org.apache.commons.configuration.PropertiesConfiguration; 
import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy; 

public class MyApplicationProperties { 
    private static PropertiesConfiguration configuration = null; 

    static { 
     try { 
      configuration = new PropertiesConfiguration("test.properties"); 
     } catch (ConfigurationException e) { 
      e.printStackTrace(); 
     } 
     configuration.setReloadingStrategy(new FileChangedReloadingStrategy()); 
    } 

    public static synchronized String getProperty(final String key) { 
     return (String) configuration.getProperty(key); 
    } 
} 

e testarlo con:

package corejava.reloadTest; 

public class TestReloading { 
    public static void main(String[] args) { 
     while (true) { 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println(MyApplicationProperties.getProperty("key")); 
     } 
    } 
} 

uscita quando si cambia test.properties è qualcosa di simile questo (contenuto originale del test.props era chiave = valore, poi cambiato in chiave = valore1 esecuzione a metà del programma):

value 
value 
value 
value 
value 
Jan 17, 2015 2:05:26 PM org.apache.commons.configuration.PropertiesConfiguration reload 
INFO: Reloading configuration. URL is file:/D:/tools/workspace /AutoReloadConfigUsingApacheCommons/resources/test.properties 
value1 
value1 
value1 

Si potrebbe anche considerare ufficiale Spring Framework R documento di riferimentoRefreshable beans, utilizzando un DSL come Groovy per questo.

+0

cosa succede se immobili a file jar? –

3

il PropertyPlaceholderConfigurer bisogno di essere override per ricaricare le nuove proprietà

È necessario riscrivere processProperties metodo per rendere la StringValueResolver che contiene le proprietà sono diventati per caricabile. Questo è il mio codice

import java.io.IOException; 
import java.util.Properties; 
import org.springframework.beans.BeansException; 
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; 
import org.springframework.util.PropertyPlaceholderHelper; 
import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver; 
import org.springframework.util.StringValueResolver; 


public class ReloadablePropertyPlaceholderConfigurer 
            extends PropertyPlaceholderConfigurer { 

    private ReloadablePlaceholderResolvingStringValueResolver reloadableValueResolver; 


    public void reloadProperties() throws IOException { 
     Properties props = mergeProperties(); 
     this.reloadableValueResolver.refreshProperties(props); 
    } 


    @Override 
    protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props) 
      throws BeansException { 
     this.reloadableValueResolver = new ReloadablePlaceholderResolvingStringValueResolver(props); 
     StringValueResolver valueResolver = this.reloadableValueResolver; 
     this.doProcessProperties(beanFactoryToProcess, valueResolver); 
    } 


    private class ReloadablePlaceholderResolvingStringValueResolver 
      implements StringValueResolver { 

     private final PropertyPlaceholderHelper helper; 
     private final ReloadablePropertyPlaceholderConfigurerResolver resolver; 

     public ReloadablePlaceholderResolvingStringValueResolver(Properties props) { 
      this.helper = new PropertyPlaceholderHelper(placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders); 
      this.resolver = new ReloadablePropertyPlaceholderConfigurerResolver(props); 
     } 

     @Override 
     public String resolveStringValue(String strVal) throws BeansException { 
      String value = this.helper.replacePlaceholders(strVal, this.resolver); 
      return (value.equals(nullValue) ? null : value); 
     } 

     private void refreshProperties(Properties props){ 
      this.resolver.setProps(props); 
     } 
    } 

    private class ReloadablePropertyPlaceholderConfigurerResolver 
      implements PlaceholderResolver { 

     private Properties props; 
     private ReloadablePropertyPlaceholderConfigurerResolver(Properties props) { 
      this.props = props; 
     } 

     @Override 
     public String resolvePlaceholder(String placeholderName) { 
      return ReloadablePropertyPlaceholderConfigurer.this.resolvePlaceholder(placeholderName, props, SYSTEM_PROPERTIES_MODE_FALLBACK); 
     } 

     public void setProps(Properties props) { 
      this.props = props; 
     } 
    } 
} 

Qui è la configurazione per properties-config.xml .all di queste proprietà può essere ricaricata in runtime come un fagiolo prototipo.

<bean id="propertyConfigurer" class="com.cn21.mail189.analysis.commons.expand.ReloadablePropertyPlaceholderConfigurer"> 
    <property name="ignoreUnresolvablePlaceholders" value="true" /> 
    <property name="locations"> 
     <list> 
      <!-- database config --> 
      <value>classpath:spring/dbconfig.properties</value> 
      <!-- app config --> 
      <value>classpath:spring/app.properties</value> 
      <!-- some other config --> 
      <value>classpath:xxxx.properties</value> 
     </list> 
    </property> 
</bean>` 
+0

Benvenuti in SO. Aiuta se puoi aggiungere codice per mostrare la risposta. –

+0

in 'processProperties' passiamo' StringValueResolver' in 'doProcessProperties' che verrebbe memorizzato in beanfactory. Il valore predefinito 'PlaceholderResolvingStringValueResolver' nella classe' PlaceholderConfigurerSupport' contiene 'PropertyPlaceholderConfigurerResolver' che mantiene le proprietà in attritube finale quando lo si inserisce nel metodo 'getContext', è necessario riscriverlo – Nonlone

+0

Come possiamo riflettere queste modifiche delle proprietà in un bean predefinito? – Feng

0

All'interno applicationContext.xml

<bean id="beanId" class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy"> 
    <property name="refreshDelay" value="30000" /> <!-- 30 seconds --> 
</bean> 
<bean id="reloadableProperties" class="org.apache.commons.configuration.PropertiesConfiguration"> 
    <constructor-arg value="file:/web/${weblogic.Domain}/${weblogic.Name}/${app.Name}/reloadable_cfg/Reloadable.properties"/> 
    <property name="reloadingStrategy" ref="propertiesReloadingStrategy"/> 
</bean> 
+0

Come possiamo riflettere queste proprietà su un bean predefinito? – Feng