2014-11-14 13 views
5

Esiste un modo per caricare una classe contrassegnata con @ConfigurationProperties senza utilizzare direttamente un contesto di primavera? Fondamentalmente voglio riutilizzare tutta la logica intelligente che Spring fa, ma per un bean che istanzia manualmente manualmente al di fuori del ciclo di vita di Spring.Posso caricare manualmente @ConfigurationProperties senza Spring AppContext?

Ho un fagiolo che carica felicemente in primavera (avvio) e posso iniettare questo nei miei altri fagioli di servizio:

@ConfigurationProperties(prefix="my") 
public class MySettings { 
    String property1; 
    File property2; 
} 

Vedere la Docco primavera per ulteriori informazioni http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-command-line-args

Ma ora ho bisogno per accedere a questo bean da una classe creata all'esterno di Spring (da Hibernate). La classe viene creata così presto nel processo di avvio dell'app che Spring Boot non ha ancora reso disponibile il contesto dell'applicazione tramite i metodi di ricerca di lookup classici o riferimenti statici roll-my-own.

Così, invece voglio fare qualcosa di simile:

MySettings mySettings = new MySettings(); 
SpringPropertyLoadingMagicClass loader = new SpringPropertyLoadingMagicClass(); 
loader.populatePropertyValues(mySettings); 

E hanno MySettings finiscono con tutti i suoi valori caricati, dalla riga di comando, le proprietà del sistema, app.properties, ecc C'è qualche classe in Spring che fa qualcosa del genere o è anche tutto intrecciato con il contesto dell'applicazione?

Ovviamente potrei semplicemente caricare il file delle Proprietà da solo, ma voglio davvero mantenere la logica di Spring Boot usando le variabili della riga di comando (ad esempio --my.property1 = xxx), o le variabili di sistema o application.properties o anche a il file yaml, così come la sua logica attorno al binding rilassato e alla conversione del tipo (ad esempio property2 è un file) in modo che tutto funzioni esattamente come quando è usato nel contesto Spring.

Possibile o sogno da pipa?

Grazie per il vostro aiuto!

risposta

4

La classe "magica" che stai cercando è PropertiesConfigurationFactory. Ma metterei in dubbio il tuo bisogno di farlo - se hai solo bisogno di legare una volta, allora Spring dovrebbe essere in grado di farlo per te, e se hai problemi di ciclo di vita sarebbe meglio indirizzarli (nel caso in cui rompessero qualcos'altro).

6

Ho avuto lo stesso "problema". Ecco come l'ho risolto in SpringBoot versione 1.3.xxx e 1.4.1.

Diciamo che abbiamo il seguente file di configurazione YAML:

foo: 
    apis: 
     - 
     name: Happy Api 
     path: /happyApi.json?v=bar 
     - 
     name: Grumpy Api 
     path: /grumpyApi.json?v=grrr 

e abbiamo la seguente ConfigurationProperties:

@ConfigurationProperties(prefix = "foo") 
public class ApisProperties { 
    private List<ApiPath> apis = Lists.newArrayList(); 

    public ApisProperties() { 
    } 

    public List<ApiPath> getApis() { 
     return apis; 
    } 

    public static class ApiPath { 
     private String name; 
     private String path; 

     public String getName() { 
      return name; 
     } 

     public void setName(final String aName) { 
      name = aName; 
     } 

     public String getPath() { 
      return path; 
     } 

     public void setPath(final String aPath) { 
      path = aPath; 
     } 
    } 
} 

Poi, di fare le cose "magici" della primavera Boot a livello di programmazione (ad esempio, il caricamento di alcune proprietà in un metodo statico), è possibile eseguire:

private static ApisProperties apiProperties() { 
    try { 
     ClassPathResource resource; 
     resource = new ClassPathResource("/config/application.yml"); 

     YamlPropertiesFactoryBean factoryBean; 
     factoryBean = new YamlPropertiesFactoryBean(); 
     factoryBean.setSingleton(true); // optional depends on your use-case 
     factoryBean.setResources(resource); 

     Properties properties; 
     properties = factoryBean.getObject(); 

     MutablePropertySources propertySources; 
     propertySources = new MutablePropertySources(); 
     propertySources.addLast(new PropertiesPropertySource("apis", properties)); 

     ApisProperties apisProperties; 
     apisProperties = new ApisProperties(); 

     PropertiesConfigurationFactory<ApisProperties> configurationFactory; 
     configurationFactory = new PropertiesConfigurationFactory<>(apisProperties); 
     configurationFactory.setPropertySources(propertySources); 
     configurationFactory.setTargetName("foo"); // it's the same prefix as the one defined in the @ConfigurationProperties 

     configurationFactory.bindPropertiesToTarget(); 
     return apisProperties; // apiProperties are fed with the values defined in the application.yaml 

    } catch (BindException e) { 
     throw new IllegalArgumentException(e); 

    } 
} 
+0

Grazie per la tua risposta dettagliata! Mi aiuta molto. – Rib47

Problemi correlati