«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > Раскрываем проблемы с помощью @Named

Раскрываем проблемы с помощью @Named

Опубликовано 2 сентября 2024 г.
Просматривать:431

В постоянно развивающемся мире контекстов и внедрения зависимостей (CDI) разработчики часто сталкиваются с препятствиями, связанными с именованием компонентов, реализациями по умолчанию и потенциальными конфликтами. В этой статье представлено подробное исследование потенциальных ошибок, связанных с аннотацией @Named в CDI. Мы углубимся в его тонкости, прольем свет на проблемные сценарии и обсудим альтернативные подходы, включая использование @Identifier от SmallRye. Кроме того, мы предложим лучшие практики для создания надежных и удобных в обслуживании Jakarta EE
приложения.

Понимание @Default

Аннотация @Default — ценный инструмент в CDI для явного обозначения конкретной реализации как реализации по умолчанию для данного интерфейса или типа компонента. Это вступает в игру при работе с несколькими реализациями одного и того же интерфейса, позволяя разработчикам указать, какая реализация должна быть внедрена по умолчанию, когда другие квалификаторы не используются.

Рассмотрим сценарий, в котором существует несколько реализаций интерфейса GreetingService:

@Default
public class DefaultGreetingService implements GreetingService {

  @Override
  public String greet(String name) {
    return "Hello, "   name;
  }
}
public class SpecialGreetingService implements GreetingService {

  @Override
  public String greet(String name) {
    return "Greetings, "   name   "!";
  }
}

При внедрении bean-компонента без указания каких-либо квалификаторов CDI использует bean-компонент с пометкой @Default в качестве значения по умолчанию. Это полезно в сценариях с несколькими реализациями, обеспечивая четкий выбор по умолчанию.

@Inject
private GreetingService greetingService; // Injects the @Default implementation

Хотя использование @Default не является обязательным, оно настоятельно рекомендуется, особенно при работе с интерфейсами, имеющими несколько реализаций. Он обеспечивает четкую и последовательную опцию по умолчанию, предотвращая двусмысленность и неожиданное поведение во время внедрения компонента.

Исследование @Named — палка о двух концах

Квалификатор @Named играет фундаментальную роль в CDI, присваивая bean-компоненту удобочитаемое имя или идентификатор. Разработчики часто используют его для обращения к компонентам по имени при внедрении их в другие компоненты.

Однако у @Named есть свои проблемы, особенно при использовании без дополнительных квалификаторов. По умолчанию CDI связывает неполное имя класса с именем компонента. Это может привести к конфликтам с квалификатором @Default, что приведет к неожиданному поведению во время внедрения компонента.

@Named
public class MyBean {
  // Implementation
}

При внедрении MyBean без явных квалификаторов CDI добавит только квалификатор @Named, а не квалификатор @Default. Квалификатор @Default применяется только в том случае, если он явно указан в компоненте или его квалификаторах.

@Inject
private MyBean myBean;

В этом случае может возникнуть неоднозначность, если существуют другие компоненты с таким же именем типа. Например, если существует другой компонент с именем MyBean, внедрение приведет к неоднозначности.

Чтобы решить эту проблему, разработчикам следует явно указать компонент, который они собираются внедрить.

@Inject
@Named("myBean")
private MyBean myBean;

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

Проблемные случаи: двусмысленность и непреднамеренные значения по умолчанию

Неоднозначность возникает, когда @Named используется без дополнительных квалификаторов и существует несколько реализаций одного и того же типа. Рассмотрим следующий сценарий:

@Named
public class ServiceA implements Service {
  // Implementation
}
@Named
public class ServiceB implements Service {
  // Implementation
}

Внедрение Service без явных квалификаторов может привести к неоднозначности, поскольку оба bean-компонента совпадают по типу, и никакое имя или квалификатор не различают их.

@Inject
private Service service;

В этом случае CDI не добавляет неявно @Default и не пытается разрешить неоднозначность, что приводит к неудачному внедрению из-за неоднозначной зависимости.

Альтернативы: введение @Identifier от SmallRye Common

Признавая проблемы, связанные с @Named, разработчики часто ищут альтернативы для более явного контроля над идентификацией компонентов. Одной из таких альтернатив является аннотация @Identifier из
МелкаяРожь обыкновенная. Эта аннотация предлагает более понятный и контролируемый подход к именованию компонентов, снижая риск конфликтов и неожиданных значений по умолчанию. В отличие от @Named, который требует уникальных значений для каждого приложения, @Identifier позволяет использовать несколько bean-компонентов с одинаковым значением идентификатора, если их типы различаются. Эта гибкость особенно полезна при работе с различными реализациями одного и того же интерфейса или связанных типов.

Чтобы использовать @Identifier, просто добавьте аннотацию к классу компонента и укажите значение идентификатора:

@Identifier("payment")
public class DefaultPaymentProcessor implements PaymentProcessor {
  // Implementation
}
@Identifier("payment")
public class LegacyPaymentGateway implements PaymentGateway {
  // Implementation
}

Внедрить bean-компоненты с помощью @Identifier очень просто:

public class Client {
  @Inject
  @Identifier("payment")
  PaymentProcessor processor;

  @Inject
  @Identifier("payment")
  PaymentGateway gateway;

}

Здесь значение @Identifier «платежа» повторно используется для нескольких bean-компонентов, поскольку типы PaymentProcessor и PaymentGateway различаются. Такая гибкость не поддерживается @Named, где
значения должны быть уникальными для всего приложения.

Другая альтернатива @Named — создание собственных квалификаторов. Пользовательские квалификаторы — это определяемые пользователем аннотации, которые можно использовать для идентификации и квалификации компонентов. Они предлагают наиболее детальный контроль над выбором компонентов и могут быть адаптированы к конкретным потребностям приложения.

Чтобы создать собственный квалификатор, выполните следующие действия:

  1. Определите новый класс аннотаций.
  2. Добавьте аннотацию к классу аннотаций с помощью @Qualifier.
  3. При желании укажите для квалификатора значение по умолчанию.

Например, следующий пользовательский квалификатор с именем DefaultPaymentGateway указывает реализацию платежного шлюза по умолчанию:

@Qualifier
@Retention(RUNTIME)
@Target({METHOD, FIELD, PARAMETER, TYPE})
public @interface DefaultPaymentGateway {

}

Чтобы использовать пользовательский квалификатор, аннотируйте им класс компонента:

@DefaultPaymentGateway
public class StandardPaymentGateway implements PaymentGateway {
  // Implementation
}
public class ExpressPaymentGateway implements PaymentGateway {
  // Implementation
}

Затем внедрите компонент, используя квалификатор:

@Inject
@DefaultPaymentGateway
private PaymentGateway paymentGateway;

Выбор правильного подхода

Лучший подход к идентификации bean-компонентов зависит от конкретных потребностей приложения. Для простых приложений @Named может быть достаточно. Для более сложных приложений @Identifier или
пользовательские квалификаторы обеспечивают больше контроля и гибкости.

В следующей таблице приведены плюсы и минусы каждого подхода:

Подход Плюсы Минусы
@Имя Простой, широко поддерживаемый Может быть неоднозначным, конфликтует с @Default
@Идентификатор Более четкая идентификация, отсутствие конфликтов с @Default Требуются дополнительные аннотации
Пользовательские квалификаторы Максимальная гибкость, детальный контроль Требуются предварительные усилия по определению и поддержанию

Для дальнейшего подтверждения вы можете обратиться к официальной спецификации CDI

Unveiling Challenges with @Named

Заключение: стратегический выбор имен компонентов и значений по умолчанию

В заключение, потенциальные ловушки, связанные с @Named, подчеркивают необходимость тщательного рассмотрения при использовании этой аннотации в CDI. При использовании неявного именования могут возникнуть неоднозначность и непреднамеренные значения по умолчанию, особенно при наличии нескольких реализаций. Разработчикам рекомендуется изучить альтернативы, такие как @Identifier от SmallRye Common для более контролируемого и явного подхода к идентификации компонентов. Использование явной квалификации, пользовательских квалификаторов и альтернативных подходов обеспечивает более плавную и контролируемую работу CDI, что приводит к созданию надежной и удобной в обслуживании Java.

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/yanev/unveiling-challenges-with-named-67p?1. Если есть какие-либо нарушения, свяжитесь с [email protected], чтобы удалить ее.
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3