Почему аннотация @Qualifier не работает с конечной переменной-членом

Я заметил, что аннотация @Qualifier не работает с переменной-членом final. В приведенном ниже коде

  • если Vehicle переменная-член Person объявлена ​​как final, возникает исключение;
  • в противном случае исключение не генерируется (но vehicle равно нулю).

Кто-нибудь может объяснить, почему?

// 2 Vehicle beans are annotated by @Qualifier;
@Configuration
public class Config 
{
  @Bean
  @Qualifier("vehicle1")
  Vehicle vehicle1() {
    var veh = new Vehicle();
    veh.setName("Benz");
    return veh;
  }

  @Bean
  @Qualifier("vehicle2")
  Vehicle vehicle2() {
    var veh = new Vehicle();
    veh.setName("BMW");
    return veh;
  }
}

// Person has a final member variable Vehicle
@Component
@Data
public class Person 
{
  private String name = "Mike";

  @Qualifier("vehicle2")
  private final Vehicle vehicle;
}

Springboot жалуется на NoUniqueBeanDefinitionException:

  • Нет подходящего компонента типа «project1.Vehicle»: ожидается один соответствующий компонент, но найдено 2: транспортное средство1, транспортное средство2
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
0
70
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема тесно связана с ломбоком, что встречается довольно часто.

Я бы предложил для такой проблемы посмотреть на обработанный класс.

Если вы используете IntelliJ, перейдите в каталог сборки проекта, чтобы открыть файл класса.

1. если переменная-член Vechicle для Person объявлена ​​как final, генерируется исключение;

Обработанный класс:

@Component
public class Person {
    private String name = "Mike";
    @Qualifier("vehicle2")
    private final Vehicle vehicle;

    public Person(final Vehicle vehicle) {
        this.vehicle = vehicle;
    }
    ...
}

Мы видим, что в данном случае внедрение осуществляется через конструктор, а @Qualifier игнорируется. Следовательно, мы увидим NoUniqueBeanDefinitionException, поскольку мы не указываем, какой компонент использовать.

2. в противном случае исключение не генерируется (но транспортное средство равно null).

На этот раз обработанный класс:

@Component
public class Person {
    private String name = "Mike";
    @Qualifier("vehicle2")
    private Vehicle vehicle;

    public Person() {
    }
    ...
}

vehicle на этот раз не появляется в конструкторе, и нет @Autowired для `транспортного средства, поэтому впрыск не выполняется, и он равен нулю.

Как заставить это работать?

Начнем с того, что не принято использовать @Data с компонентом Spring, @Data обычно используется DTO. И в пользу внедрения конструктора я изменю Person, как показано ниже.

@Component
public class Person {
    private String name = "Mike";
    private final Vehicle vehicle;
    public Person(@Qualifier("vehicle2") Vehicle vehicle) {
        this.vehicle = vehicle;
    }
    // ... getter setter omitted
}

Отличный ответ - не только ответ, но и подход к нему и способ решения проблемы!

leo 12.04.2023 07:07

Другие вопросы по теме