Can I manually download @ConfigurationProperties without Spring AppContext?

Is there a way to load a class with @ConfigurationProperties without directly using the Spring context? Basically, I want to reuse all the smart logic that Spring does, but for a bean, I manually create an instance outside the Spring life cycle.

I have a bean that loads with joy in Spring (Boot), and I can paste it into another beans service:

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

See Spring docco for more information http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-features-external-config-command-line-args

But now I need to access this bean from a class created outside of Spring (by Hibernate). The class is created so early in the process of running the application that Spring Boot has not yet made the application context accessible using classic helper search methods or static links made manually.

So instead I want to do something like:

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

And I have MySettings with all its values ​​loaded from the command line, system properties, app.properties, etc. Is there some class in Spring that does something like this, or is it all too intertwined with the application context?

Obviously, I can just load the properties file myself, but I really want to support Spring loading logic using command line variables (e.g. --my.property1 = xxx) or system variables or application.properties or even a yaml file as well the logic around relaxed type binding and conversion (for example, property2 is a file), so that everything works exactly the same as when used in a Spring context.

Is dream or dream possible?

Thanks for your help!

+5
source share
2 answers

The magic class you are looking for is PropertiesConfigurationFactory . But I would question your need for it - if you only need to bind once, then Spring will be able to do it for you, and if you have problems with the life cycle, it would be better to contact them (if they break something yet).

+5
source

I had the same "problem". This is how I solved it in SpringBoot version 1.3.xxx and 1.4.1.

Let's say we have the following yaml configuration file:

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

and we have the following 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; } } } 

Then, to do the “magic” things of Spring Boot programmatically (for example, loading some properties into a static method), you can do:

 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 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); } } 
+7
source

Source: https://habr.com/ru/post/1206925/


All Articles