2014-11-14 13 views
5

Czy istnieje sposób na załadowanie klasy oznaczonej @ConfigurationProperties bez bezpośredniego kontekstu wiosennego? Zasadniczo chcę ponownie wykorzystać całą inteligentną logikę, którą wykonuje Spring, ale w przypadku komponentu bean, który ręcznie inicjuję poza cyklem życia Spring.Czy mogę ręcznie załadować @ConfigurationProperties bez Spring AppContext?

Mam fasoli, która ładuje się szczęśliwie na wiosnę (boot) i mogę wstrzyknąć to do moich innych ziaren Usługa:

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

Zobacz docco sprężyny, aby uzyskać więcej informacji http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-command-line-args

Ale teraz muszę aby uzyskać dostęp do tego komponentu bean z klasy utworzonej poza wiosną (przez Hibernate). Klasa jest tworzona na tak wczesnym etapie procesu uruchamiania aplikacji, że Spring Boot nie udostępnił jeszcze kontekstu aplikacji za pomocą klasycznych metod pomocniczych odnośnika lub statycznych referencji roll-my-own.

Więc zamiast chcą zrobić coś takiego:

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

I mieć MySettings skończyć ze wszystkimi jego wartości ładowanych z wiersza polecenia Właściwości systemu app.properties itp Czy jest jakaś klasa w Wiosna, która robi coś takiego, czy też wszystko jest zbyt przeplatane z kontekstem aplikacji?

Oczywiście mogłem po prostu załadować plik Właściwości sam, ale naprawdę chcę zachować logikę Spring Boot przy użyciu zmiennych wiersza poleceń (np. - my.property1 = xxx), lub zmiennych systemowych, application.properties lub nawet plik yaml, a także logika wokół luźnego powiązania i konwersji typów (np. właściwość 2 to plik), tak aby wszystko działało dokładnie tak samo, jak w kontekście wiosennym.

Możliwe czy marzenie?

Dzięki za pomoc!

Odpowiedz

4

Klasa "magia" której szukasz, to PropertiesConfigurationFactory. Ale chciałbym zakwestionować twoją potrzebę - jeśli potrzebujesz tylko raz związać, wtedy Wiosna powinna być w stanie zrobić to za Ciebie, a jeśli masz problemy z cyklem życia, lepiej byłoby je rozwiązać (na wypadek, gdyby złamały coś innego).

6

Miałem ten sam "problem". Oto jak rozwiązałem go w SpringBoot w wersji 1.3.xxx i 1.4.1.

Załóżmy, że mamy następujący plik konfiguracyjny yaml:

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

i mamy następujące 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; 
     } 
    } 
} 

Następnie, aby robić rzeczy, "magiczne" Spring Boot programowo (np. ładowanie niektórych właściwości metodą statyczną), można wykonać:

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

Dziękujemy za szczegółową odpowiedź! To mi bardzo pomaga. – Rib47

Powiązane problemy