@Квалификатор весной в дополнение к классам

#java #spring

Вопрос:

Я играл в Spring/Spring Boot и заметил кое-что странное, в чем я не могу разобраться самостоятельно, поэтому буду признателен за любую помощь.

Допустим, у нас есть следующее

 public interface ICar {}
 
 @Component
public class CarOne implements ICar {}
 
 @Component
public class CarTwo implements ICar {}
 
 public class Driver {
        
    @Autowired
    private ICar car;

}
 

Я запускаю программу Spring Boot, так что все настроено правильно, это для простоты.
На этом этапе, если мы запустим нашу программу, мы получим исключение из-за неоднозначности. Теперь в соответствии с https://www.baeldung.com/spring-qualifier-annotation если мы добавим @Qualifier поверх @Component класса, он должен изменить имя компонента этого класса. Так, например, если мы изменим CarOne класс на:

 @Component
@Qualifier("car")
public class CarOne implements ICar {}
 

Имя боба должно быть car таким .

Основываясь на документации Spring, @Autowired использует имя поля в качестве квалификатора по умолчанию, если таковой не указан, таким образом, мы сможем успешно запустить нашу программу, так @Autowired как поле в классе Driver ищет компонент с именем car , и он у нас уже есть. Этого не происходит, тхо. Я снова получаю то же исключение, касающееся двусмысленности. Теперь , если я добавлю @Qualifier("car") , вместе с @Autowired тем, все будет работать нормально.

Я в замешательстве, потому что, если мы изменим, например @Autowired , поле на carOne или carTwo (не добавляя @Qualifier его поверх @Component классов), программа снова будет работать правильно. Я предполагаю, что это как-то связано с различием типа/имени, но не могу понять этого. Может ли кто-нибудь, обладающий немного большими знаниями, объяснить, почему это может происходить?

P. S: Я имею в виду статью баельдунга, так как я не смог найти ничего лучшего в официальном весеннем документе, касающемся использования @Qualifier поверх классов.

Комментарии:

1. Нет, это не так. Он добавляет квалификатор, он не изменяет имя компонента. Если вы хотите изменить имя компонента, сделайте @Component("car") это . Квалификатор-это не имя компонента, это разные метаданные, позволяющие различать несколько различных реализаций/экземпляров класса.

2. О, ладно. Теперь я понимаю. Ну, я думаю, что тогда утверждение, что @Component(«автомобиль») и @Component @Квалификатор(«автомобиль») неверно. Спасибо!

3. Утверждение, упомянутое в руководстве, является правильным. Они не утверждают, что это изменяет название компонента, вместо этого они упоминают, чтобы добиться того же эффекта.

Ответ №1:

Использование @Qualifier в компоненте не изменяет имя. Он добавляет, как следует из названия, квалификатор к метаданным компонента. Эти метаданные (квалификатор) можно использовать для выбора экземпляра класса для использования.

Поэтому, если вы прокомментировали один из них, @Qualifier("car") вам также нужно добавить его в точку инъекции (если это то, что вы хотите).

Вы также можете использовать @Qualifer в качестве мета-аннотации, то есть вы можете создать аннотацию с этой аннотацией и использовать ее в качестве метаданных.

Что-то вроде

 @Qualifier
public @interface SimpleCar {}
 

Теперь вы можете пометить свой CarOne (например) с @SimpleCar помощью и также поместить это в @Autowired поле. Что, вероятно, яснее, чем использование имен/строк для квалификации вещей.

Вы также можете использовать @Qualifier("carOne") это @Autowired поле, чтобы указать, какой из них использовать (так как имя компонента используется в качестве запасного варианта). Однако недостатком является то, что вам нужно знать имя (поэтому предпочтительнее использовать конкретные аннотации-классификаторы).

Теперь для @Autowired этого по умолчанию работает тип. Поэтому в этом случае он попытается найти один Car экземпляр. У вас есть больше, чем это, и поэтому в качестве запасного варианта он попытается сопоставить имя поля с именем компонента ( car здесь), поскольку это не так, он потерпит неудачу. Если вы измените значение CarOne на @Component("car") , оно также будет работать без дальнейших изменений, так как теперь у вас есть компонент, соответствующий типу и имени поля. Однако снова полагаться на это, как правило, плохая идея (одно изменение стратегии именования, имя класса и прочее ломаются).