Spring @Autowired and @Value on property not working
Asked Answered
V

3

11

I would like to use @Value on a property but I always get 0(on int).
But on a constructor parameter it works.

Example:

@Component
public class FtpServer {

    @Value("${ftp.port}")
    private int port;

    public FtpServer(@Value("${ftp.port}") int port) {
        System.out.println(port); // 21, loaded from the application.properties.
        System.out.println(this.port); // 0???
    }
}

The object is spring managed, else the constructor parameter wouldn't work.

Does anyone know what causes this weird behaviour?

V2 answered 4/9, 2017 at 11:23 Comment(2)
Constructor and class name don't match, I guess is a typoHeirloom
How can Spring set a value on an object that doesn't even exist... An object exists AFTER the execution of a constructor.Adair
C
25

Field injection is done after objects are constructed since obviously the container cannot set a property of something which doesn't exist. The field will be always unset in the constructor.

If you want to print the injected value (or do some real initialization :)), you can use a method annotated with @PostConstruct, which will be executed after the injection process.

@Component
public class FtpServer {

    @Value("${ftp.port}")
    private int port;

    @PostConstruct
    public void init() {
        System.out.println(this.port);
    }

}
Corrade answered 4/9, 2017 at 11:29 Comment(1)
I did not know about that @PostConstruct annotation...+1 I've learnt something new!Heirloom
H
7

I think the problem is caused because Spring's order of execution:

  • Firstly, Spring calls the constructor to create an instance, something like:

    FtpServer ftpServer=new FtpServer(<value>);

  • after that, by reflection, the attribute is filled:

    code equivalent to ftpServer.setPort(<value>)

So during the constructor execution the attribute is still 0 because that's the default value of an int.

Heirloom answered 4/9, 2017 at 11:29 Comment(0)
M
1

This is a member injection:

@Value("${ftp.port}")
private int port;

Which spring does after instantiating the bean from its constructor. So at the time spring is instantiating the bean from the class, spring has not injected the value, thats why you are getting the default int value 0.

Make sure to call the variable after the constructor have been called by spring, in case you want to stick with member injection.

Mainsheet answered 4/9, 2017 at 18:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.