Spring @Autowired и @Value для свойства не работают

Я хотел бы использовать @Value для свойства, но всегда получаю 0(для int).
Но для параметра конструктора это работает.

Пример:

@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???
    }
}

Объект управляется пружиной, иначе параметр конструктора не будет работать.

Кто-нибудь знает, в чем причина такого странного поведения?


person Jan Wytze    schedule 04.09.2017    source источник
comment
Конструктор и имя класса не совпадают, я думаю, это опечатка   -  person Pablo Lozano    schedule 04.09.2017
comment
Как Spring может установить значение для объекта, которого даже не существует... Объект существует ПОСЛЕ выполнения конструктора.   -  person M. Deinum    schedule 04.09.2017


Ответы (3)


Внедрение поля выполняется после создания объектов, поскольку очевидно, что контейнер не может установить свойство чего-то, чего не существует. Поле всегда будет не задано в конструкторе.

Если вы хотите напечатать введенное значение (или выполнить настоящую инициализацию :)), вы можете использовать метод с аннотацией @PostConstruct, который будет выполняться после процесса внедрения.

@Component
public class FtpServer {

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

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

}
person Daniel Olszewski    schedule 04.09.2017
comment
Я не знал об этой аннотации @PostConstruct... +1 Я узнал кое-что новое! - person Pablo Lozano; 04.09.2017

Я думаю, что проблема вызвана тем, что порядок выполнения Spring:

  • Во-первых, Spring вызывает конструктор для создания экземпляра, например:

    FtpServer ftpServer=new FtpServer(<value>);

  • после этого путем отражения атрибут заполняется:

    code equivalent to ftpServer.setPort(<value>)

Таким образом, во время выполнения конструктора атрибут по-прежнему равен 0, потому что это значение по умолчанию для int.

person Pablo Lozano    schedule 04.09.2017

Это инъекция члена:

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

Что делает Spring после создания экземпляра bean-компонента из его конструктора. Таким образом, в то время, когда Spring создает экземпляр bean-компонента из класса, Spring не вводит значение, поэтому вы получаете значение int по умолчанию 0.

Обязательно вызывайте переменную после того, как конструктор был вызван Spring, если вы хотите придерживаться внедрения члена.

person Raymond Stanley    schedule 04.09.2017