В Java EE CDI как можно всегда знать, в какой области должен быть объявлен компонент CDI? - PullRequest
0 голосов
/ 29 августа 2018

Я пробираюсь через учебник по Java EE 8, и у меня возникло некоторое замешательство новичка по поводу областей применения. Я новичок в этом, поэтому, пожалуйста, потерпите меня, если это глупый вопрос. Насколько я понимаю, CDI позволяет любому классу, который был аннотирован областью действия, например @RequestScoped, вводиться в сервлет. Пример, приведенный в руководстве по https://javaee.github.io/tutorial/cdi-basic001.html:

@RequestScoped
public class MessageB implements Message { ... }

, что позволяет это:

@WebServlet("/cdiservlet")
public class NewServlet extends HttpServlet {
    @Inject private Message message;

    @Override
    public void doGet(HttpServletRequest request, HttpServletResponse response)
                  throws IOException {
        response.getWriter().write(message.get());
    }
}

что очень хорошо и легко понять, но ....

У меня вопрос: не связывает ли это и / или не ограничивает ли использование класса MessageB в сервлете? Что если класс, который должен использоваться в качестве компонента CDI, необходимо использовать в области запросов в одном случае использования, сервлете или приложении и области сеанса в другом, и, возможно, области приложения в другом? Как это должно работать? Предполагается ли, что разработчик класса предусматривает максимально широкую область применения (особенно при написании класса, который будет использоваться другими разработчиками)? Если так, что если клиент, использующий этот класс, хочет использовать его, например, в области запроса? Просто кажется, что у нас должен быть слабосвязанный код, но привязка класса к области действия ограничивает способ использования этого класса способом, который может оказаться бесполезным или логичным. Или всегда предполагается, что компоненты, которые используются таким образом, созданы самим разработчиком приложения?
Заранее спасибо за любые идеи.

Редактировать: Пройдя немного дальше, кажется, что @Qualifier является решением этих проблем. Разработчик должен предоставить разные подтипы (например, путем реализации интерфейса или расширения класса), а затем использовать атрибут @Qualifier с каждым отдельным типом.

https://javaee.github.io/tutorial/cdi-basic006.html

https://dzone.com/articles/define-cdi-qualifier

1 Ответ

0 голосов
/ 29 августа 2018

Да, вы можете использовать различные компоненты CDI интерфейса Message с различными областями действия CDI. Лучшей практикой для этого подхода будет определение нескольких аннотаций, таких как

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

И затем вы можете добавить @SessionMessage например. над вашим @SessionScope бобом и введите этот боб сообщения с @Inject @SessionMessage private Message message.

Другим подходом может быть стандартная область действия @Dependet CDI, которая используется, если вы не определяете какую-либо область действия в своем компоненте CDI. С этой областью вы достигаете следующего:

@ Зависимый: область по умолчанию, если она не указана; это означает, что объект существует для обслуживания ровно одного клиента (бина) и имеет тот же жизненный цикл, что и этот клиент (бин). (https://docs.oracle.com/javaee/6/tutorial/doc/gjbbk.html)

С помощью этой аннотации вы наследуете область действия клиентского компонента. Поэтому, если вы введете свой Message в @RequestScoped bean-компонент, ваш Message будет иметь такой же жизненный цикл.

...