Search code examples
javaspring-annotations

Spring possibility to @Value on a Pojo / object


Small question regarding the spring annotation @Value please.

This annotation is powerful, well known and offers the possibility out of the box to bind types such as boolean, String, and even more complex data structures such as List, Map<String, Integer> via configuration.

    @Value("${my.string}")
    private String               myString;

    @Value("${my.flag}")
    private Boolean               someFlag;

 @Value("#{'${my.list.of.strings}'.split(',')}")
    private List<String>         myListOfStrings;

    @Value("#{${my.hashmap}}")
private Map<String, Integer> myHashMap;

application.properties
my.string=something
my.flag=true
my.list.of.strings=hello,world
my.hashmap={'hello':'world','aaa':'bbb','ccc':'ddd'}

Question: Is it possible to use @Value on some POJO I defined please? something like:

  @Value("${my.pojo}")
    private MyPojo myPojo;

public class MyPojo {
    
    private String firstName;
    private String lastName;
    private int age;
    private boolean isMarried;
    
}

application.properties
my.pojo={ "firstname": "john", "lastname": "doe", "isMarried": false, "age": 20 }

And have the @Value (or maybe something else) pick it up. I tried above and did not get the myPojo. What would be a solution to have this configurable under @Value please?

Thank you


Solution

  • Spring can not inject those values into a POJO, because by definition POJO's are not managed by Spring's IoC Container.

    If you look at the Spring documentation for the @Value annotation (linked at bottom), it specifies "Note that actual processing of the @Value annotation is performed by a BeanPostProcessor", this is pretty explicit in it's own right that the class has to be a Spring bean, but if context isn't enough, looking at the BeanPostProcessor documentation (also linked at bottom): "Factory hook that allows for custom modification of new bean instances — for example, checking for marker interfaces or wrapping beans with proxies"

    So no, if the class is not managed by Spring's IoC container (i.e., if the class is not a Spring bean), the value annotation will not be caught by the BeanPostProcessor, and will therefore not be useful.

    Value annotation doc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/annotation/Value.html

    BeanPostProcessor doc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanPostProcessor.html

    You can always go the route of using jdk-native classes to read values from properties files if that's absolutely necessary (quick example: https://www.javatpoint.com/properties-class-in-java)

    For the record, the specification of what a POJO is, means that the class cannot contain pre-specified annotations. So even in another world where @Value could work on a non-spring bean, it would still, by definition, break the POJO aspect of the class.