Spring @Autowired and @Value on property not working

10.5k views Asked by At

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?

3

There are 3 answers

1
Daniel Olszewski On BEST ANSWER

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

}
0
Pablo Lozano On

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.

0
Raymond Stanley On

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.