#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")
, оно также будет работать без дальнейших изменений, так как теперь у вас есть компонент, соответствующий типу и имени поля. Однако снова полагаться на это, как правило, плохая идея (одно изменение стратегии именования, имя класса и прочее ломаются).