18

I have a Spring-managed bean that loads properties using a property-placeholder in its associated context.xml:

<context:property-placeholder location="file:config/example.prefs" />

I can access properties using Spring's @Value annotations at initialisation, e.g.:

@Value("${some.prefs.key}")
String someProperty;

...but I need to expose those properties to other (non-Spring managed) objects in a generic way. Ideally, I could expose them through a method like:

public String getPropertyValue(String key) {
  @Value("${" + key + "}")
  String value;

  return value;
}

...but obviously I can't use the @Value annotation in that context. Is there some way I can access the properties loaded by Spring from example.prefs at runtime using keys, e.g.:

public String getPropertyValue(String key) {
  return SomeSpringContextOrEnvironmentObject.getValue(key);
}
Doches
  • 3,276
  • 2
  • 19
  • 26
  • 2
    I think this is what you're looking for: http://stackoverflow.com/questions/1771166/access-properties-file-programatically-with-spring/6817902#6817902 – Andreas Aumayr Jan 22 '14 at 07:35
  • 1
    I would create a nomral bean, that takes the spring bean as construcotr argument, the spring bean having its values already set as it was instantiated by spring. I guess this is somewhat dependent on your architecture. – NimChimpsky Jan 22 '14 at 08:27
  • Can you tell us more about what you call "non-Spring managed" – Aurélien Thieriot Jan 22 '14 at 09:43
  • Sure -- a class that's not instantiated by Spring, in which I can't get to the Spring ApplicationContext directly. All I mean by 'non-Spring managed' is 'not instantiated as a bean from XML.' – Doches Jan 22 '14 at 09:49

3 Answers3

20

Autowire the Environment object in your class. Then you will be able to access the properties using environment.getProperty(propertyName);

@Autowired
private Environment environment;

// access it as below wherever required.
 environment.getProperty(propertyName);

Also add @PropertySource on Config class.

@Configuration
@PropertySource("classpath:some.properties")
public class ApplicationConfiguration
Sangam Belose
  • 4,262
  • 8
  • 26
  • 48
  • Doesn't worked for me, the best solution was this [PropertyPlaceholderExposer](https://stackoverflow.com/a/10200249) with some simplification. –  Dec 20 '17 at 14:53
  • @SérgioMichels The approach you have mentioned uses PropertyPlaceholderConfigurer which was old approach used in spring config. https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.html docs suggest to use Enviornment. – Sangam Belose Dec 21 '17 at 06:09
  • 2
    Worked as simple as that for me. Environment environment back to basics. – SatyaRajC Nov 21 '20 at 15:27
4

inject BeanFactory into your bean.

 @Autowired
 BeanFactory factory;

then cast and get the property from the bean

((ConfigurableBeanFactory) factory).resolveEmbeddedValue("${propertie}")
Wilson Campusano
  • 616
  • 9
  • 21
  • 2
    With Spring Boot 2.2.7-RELEASE, you should `@Autowire` `ConfigurableBeanFactory` instead of `BeanFactory`. Actually it complains about `NullPointerException` if you `@Autowire` `Bean Factory`. – jrodriguez Jul 15 '20 at 13:44
  • 1
    By the way, using Autowire at member level will throw a warning which you can get rid of if you instead use `@Autowire` in a setter or constructor. – jrodriguez Jul 15 '20 at 13:45
0

You can have Spring inject the properties into a map, with a lot of benefits. The keys would be the dynamic part.

https://docs.spring.io/spring-boot/docs/2.1.13.RELEASE/reference/html/boot-features-external-config.html#boot-features-external-config-complex-type-merge displays the following example:

@ConfigurationProperties("acme")
public class AcmeProperties {

    private final Map<String, MyPojo> map = new HashMap<>();

    public Map<String, MyPojo> getMap() {
        return this.map;
    }
}

Properties

acme:
  map:
    key1:
      name: my name 1
      description: my description 1
---
spring:
  profiles: dev
acme:
  map:
    key1:
      name: dev name 1
    key2:
      name: dev name 2
      description: dev description 2
jediz
  • 4,459
  • 5
  • 36
  • 41