Невозможно ввести значение свойства в параметр класса (@Value annotatnion) - PullRequest
0 голосов
/ 10 апреля 2019

Я учу Spring Boot, и у меня, наверное, очень простой вопрос, но он мне не совсем понятен. Я столкнулся с некоторой проблемой с аннотацией @Value - я хотел бы знать, почему свойство apprication не может быть введено в параметр класса.

Я подготовил какой-то очень простой проект, используя Spring Initializr, и добавил одно свойство в свой ресурс application.properties. Кроме того, я создал два дополнительных класса: «YellowCar» (который работает нормально) и «RedCar» (который не работает - параметр не может быть правильно введен).

Файл "application.properties":

car.age=15

Основной класс моей заявки:

package com.example.helper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;

@SpringBootApplication
public class HelperApplication implements CommandLineRunner {

    @Autowired
    private Environment env;

    public static void main(String[] args) {
        SpringApplication.run(HelperApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {
        System.out.println (new RedCar(env));
        System.out.println (new YellowCar());
    }

}

RedCar создается путем передачи переменной Environment в конструктор:

package com.example.helper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

@Component
public class RedCar {

    private int age;

    @Autowired
    public RedCar (Environment env) {
        this.age = new Integer(env.getRequiredProperty("car.age")).intValue();
    }

    @Override
    public String toString() {
        return "Car [age=" + age + "]";
    }

}

YellowCar собирается без передачи переменной Environment в конструктор, но с использованием аннотации @Value:

package com.example.helper;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class YellowCar {

    @Value("${car.age}")
    private int age;

    @Override
    public String toString() {
        return "YellowCar [age=" + age + "]";
    }

}

Это вывод программы:

Car [age=15]
YellowCar [age=0]

Как видите, возраст YellowCar был введен неправильно (он равен 0).

Моя цель: я бы не хотел везде передавать объект Environment в конструктор других классов ... Вместо этого я хотел бы использовать @Value annotatnio. Может ли кто-нибудь объяснить мне: 1) почему мой код не работает? 2) как этот код должен быть обновлен, чтобы получить следующий вывод?

Car [age=15]
YellowCar [age=15]

Спасибо!

1 Ответ

0 голосов
/ 11 апреля 2019

Это происходит, потому что вы создаете экземпляр YellowCar напрямую. Чтобы все заработало, @Autowire YellowCar внутри HelperApplication и используйте этот внедренный экземпляр следующим образом (не проверено):

@Autowired
private YellowCar yellowCar;

public static void main(String[] args) {
    SpringApplication.run(HelperApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
    System.out.println (new RedCar(env));
    System.out.println (yellowCar);
}

Пояснение:

Когда вы создаете класс с помощью new, Spring ничего не знает об этом новом экземпляре, следовательно, он не может ничего внедрить. Но когда экземпляр создается через инфраструктуру Spring (я пытаюсь не использовать здесь много жаргонных слов), в него будут вставлены все поля: когда вы помечаете класс аннотацией @Component или создаете метод аннотацией @Bean, вы говорите Весна, ты хочешь, чтобы это был Боб. При запуске приложения Spring создает экземпляры этого bean-компонента - по умолчанию только один экземпляр для контекста - и внедряет этот экземпляр во все другие bean-компоненты, где это требуется. В этом случае этот экземпляр обрабатывается инфраструктурой Spring (точный класс, который это делает - AutowiredAnnotationBeanPostProcessor), и экземпляры других bean-компонентов будут внедрены в наш bean-компонент.

UPD: Вы можете сделать то же самое с RedCar:

@Autowired
private YellowCar yellowCar;

@Autowired
private RedCar redCar;

public static void main(String[] args) {
    SpringApplication.run(HelperApplication.class, args);
}

@Override
public void run(String... args) throws Exception {
    System.out.println (redCar);
    System.out.println (yellowCar);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...