Статьи

Учебное пособие по Java EE CDI Producer

Это учебник по методам CDI Producer. В CDI метод Producer генерирует объект, который затем может быть введен. Методы источника могут использоваться, когда мы хотим внедрить объект, который сам не является компонентом, когда конкретный тип объекта, который нужно внедрить, может изменяться во время выполнения или когда объект требует некоторой пользовательской инициализации, которую не выполняет конструктор компонента. Методы производителя позволяют нам представлять любой класс JDK в виде bean-компонента и определять несколько bean-компонентов с разными областями действия или инициализацией для одного и того же класса реализации. Они также позволяют нам использовать полиморфизм времени выполнения с CDI.

Здесь мы создадим простой сервис с двумя реализациями, а затем создадим метод Producer для создания и внедрения обеих реализаций в приложении.

Нашей предпочтительной средой разработки является Eclipse . Мы используем версию Eclipse Juno (4.2) вместе с плагином Maven Integration версии 3.1.0. Вы можете скачать Eclipse отсюда и Maven Plugin для Eclipse отсюда . Установка плагина Maven для Eclipse выходит за рамки данного руководства и не будет обсуждаться. Tomcat 7 — это используемый сервер приложений.

Давайте начнем,

1. Создайте новый проект Maven

Перейдите в Файл -> Проект -> Maven -> Проект Maven.

New-Maven-проект

На странице мастера «Выберите имя проекта и местоположение» убедитесь, что опция «Создать простой проект (пропустить выбор архетипа») не отмечена , нажмите «Далее», чтобы продолжить со значениями по умолчанию.

новый проект

Здесь должен быть добавлен архетип maven для создания веб-приложения. Нажмите «Добавить архетип» и добавьте архетип. Установите переменную «Archetype Group Id» на "org.apache.maven.archetypes" , переменную «Archetype ardact Id» на "maven-archetype-webapp" и «Archetype Version» на "1.0" . Нажмите «ОК», чтобы продолжить.

Maven-архетип-WebApp

На странице мастера «Введите идентификатор артефакта» вы можете определить имя и основной пакет вашего проекта. Установите для переменной «Group Id» значение "com.javacodegeeks.snippets.enterprise" а для переменной «Artifact Id» — "cdibeans" . Вышеупомянутые варианты составляют основной пакет проекта как "com.javacodegeeks.snippets.enterprise.cdibeans" а имя проекта — "cdibeans" . Установите для переменной «Package» значение "war" , чтобы создать файл war для развертывания на сервере tomcat. Нажмите «Готово», чтобы выйти из мастера и создать свой проект.

newcdiproject1

Структура проекта Maven показана ниже:

newcdiproject2

    Он состоит из следующих папок:

  • Папка / src / main / java, которая содержит исходные файлы для динамического содержимого приложения,
  • Папка / src / test / java содержит все исходные файлы для модульных тестов,
  • Папка / src / main / resources содержит файлы конфигурации,
  • Папка / target содержит скомпилированные и упакованные результаты,
  • Папка / src / main / resources / webapp / WEB-INF содержит дескрипторы развертывания для веб-приложения,
  • pom.xml — это файл объектной модели проекта (POM). Единственный файл, который содержит все связанные с проектом конфигурации.

2. Добавьте все необходимые зависимости

Вы можете добавить зависимости в файле Maven pom.xml , отредактировав его на странице «Pom.xml» редактора POM, как показано ниже:

pom.xml:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.javacodegeeks.snippets.enterprise.cdi</groupId>
    <artifactId>cdibeans</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>cdibeans Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>org.jboss.weld.servlet</groupId>
            <artifactId>weld-servlet</artifactId>
            <version>1.1.10.Final</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.faces</artifactId>
            <version>2.1.7</version>
        </dependency>
    </dependencies>
 
    <build>
        <finalName>cdibeans</finalName>
    </build>
</project>

Как видите, Maven декларативно управляет библиотечными зависимостями. Создается локальный репозиторий (по умолчанию в папке {user_home} /. M2), и все необходимые библиотеки загружаются и помещаются туда из общедоступных репозиториев. Кроме того, внутрибиблиотечные зависимости автоматически разрешаются и обрабатываются.

3. Создать простой Сервис

Служба, которая будет использоваться в источнике в этом примере, является простой службой, которая создает приветствие для приложения, которое его использует. Класс GreetingCard.java — это интерфейс с методом, который создает приветственное сообщение.

GreetingCard.java

1
2
3
4
5
6
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
public interface GreetingCard {
 
    void sayHello();
}

Реализация сервиса показана ниже:

GreetingCardImpl.java

01
02
03
04
05
06
07
08
09
10
11
package com.javacodegeeks.snippets.enterprise.cdibeans.impl;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingCard;
 
public class GreetingCardImpl implements GreetingCard {
 
    public void sayHello() {
        System.out.println("Hello!!!");
    }
 
}

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

AnotherGreetingCardImpl.java

01
02
03
04
05
06
07
08
09
10
11
12
package com.javacodegeeks.snippets.enterprise.cdibeans.impl;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingCard;
 
 
public class AnotherGreetingCardImpl implements GreetingCard {
 
    public void sayHello() {
        System.out.println("Have a nice day!!!");
    }
 
}

4. Использование производителя в управляемом бине

В приведенном ниже управляемом компоненте мы используем созданного выше производителя. В частности, в классе GreetingCardFactory.java мы создаем метод getGreetingCard() , аннотированный аннотацией @Produces . Метод возвращает правильную реализацию GreetingCard соответствии с GreetingType компонента. Таким образом, полиморфизм поддерживается.

GreetingCardFactory.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import java.io.Serializable;
 
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Produces;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;
 
@SessionScoped
public class GreetingCardFactory implements Serializable {
 
    private static final long serialVersionUID = -44416514616012281L;
 
    private GreetingType greetingType;
 
    @Produces
    public GreetingCard getGreetingCard() {
 
        switch (greetingType) {
        case HELLO:
            return new GreetingCardImpl();
        case ANOTHER_HI:
            return new AnotherGreetingCardImpl();
        default:
            return new GreetingCardImpl();
        }
    }
}

GreetingType.java является перечислением, как показано ниже:

GreetingType.java

1
2
3
4
5
6
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
public enum GreetingType {
 
    HELLO, HI;
}

Другой способ использовать полиморфизм в CDI — через @Qualifier . Мы можем создать нашу собственную аннотацию в CDI, а затем использовать ее в методе Producer чтобы получить правильную реализацию.

Greetings.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
 
import javax.inject.Qualifier;
 
@Qualifier
@Retention(RUNTIME)
@Target({ FIELD, TYPE, METHOD })
public @interface Greetings {
 
    GreetingType value();
 
}

Теперь у GreetingCardFactory может быть свой метод Producer для каждой реализации. Созданная нами аннотация используется после аннотации @Produces .

GreetingCardFactory.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import java.io.Serializable;
 
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.Produces;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;
 
 
@SessionScoped
public class GreetingCardFactory implements Serializable {
 
    private static final long serialVersionUID = -44416514616012281L;
 
    private GreetingType greetingType;
 
     
    @Produces
    @Greetings(GreetingType.HELLO)
    public GreetingCard getGreetingCard() {
        return new GreetingCardImpl();
    }
     
    @Produces
    @Greetings(GreetingType.HI)
    public GreetingCard getAnotherGreetingCard() {
        return new AnotherGreetingCardImpl();
    }
     
}

5. Сфера действия производителя

При создании метода Producer важно отметить область действия Producer . Область источника по умолчанию установлена ​​в Dependent . Но у Producer также может быть любая другая область применения в зависимости от его использования. Проблема заключается в том, что может произойти, если Producer создает управляемый компонент другой области действия. Например, мы можем создать @RequestScoped компонент @RequestScoped и внедрить его в другой bean-компонент с помощью источника, @SessionScoped как @SessionScoped . В этом случае экземпляр @RequestScoped компонента @RequestScoped который возвращает Producer будет уничтожен после завершения HTTP-запроса, и поведение bean-компонента, в котором он введен, может быть неожиданным. Чтобы избежать ссылки на уже не существующие bean-компоненты, мы можем использовать аннотацию @New при использовании метода Producer . Таким образом, новый Dependent экземпляр внедряется через источник, как показано в фрагменте кода ниже:

GreetingCardFactory.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import java.io.Serializable;
 
import javax.enterprise.context.SessionScoped;
import javax.enterprise.inject.New;
import javax.enterprise.inject.Produces;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;
 
 
@SessionScoped
public class GreetingCardFactory implements Serializable {
 
    private static final long serialVersionUID = -44416514616012281L;
     
    private GreetingCardImpl greetingCard;
     
    @Produces
    public GreetingCardImpl getGreetingCard(@New GreetingCardImpl greetingCard) {
        return greetingCard;
    }
 
     
}

6. Запустите приложение

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

GreetingServlet.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.javacodegeeks.snippets.enterprise.cdibeans.servlet;
 
import java.io.IOException;
import java.io.PrintWriter;
 
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingCard;
import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingType;
import com.javacodegeeks.snippets.enterprise.cdibeans.Greetings;
 
@WebServlet(name = "greetingServlet", urlPatterns = {"/sayHello"})
public class GreetingServlet extends HttpServlet {
 
    private static final long serialVersionUID = 2280890757609124481L;
     
    @Inject
    @Greetings(GreetingType.HELLO)
    private GreetingCard greetingCard;
 
    @Inject
    @Greetings(GreetingType.HI)
    private GreetingCard anotherGreetingCard;
 
      public void init() throws ServletException {
      }
 
      public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
          response.setContentType("text/html");
          PrintWriter out = response.getWriter();
          out.println("<h1>" + greetingCard.sayHello() + "</h1>");
          out.println("<h1>" + anotherGreetingCard.sayHello() + "</h1>");
      }
       
      public void destroy(){
      }
 
}

В приведенном выше сервлете внедрены обе реализации. Чтобы запустить пример, мы должны построить проект с Maven, а затем поместить файл war созданный в папке webbaps на tomcat. Тогда мы можем нажать на:

http://localhost/8080/cdibeans/sayHello

и результат показан ниже:

тычок

Это был учебник по методам Java EE CDI Producer.

Загрузите исходный код этого урока: CDIProducerMethodExample.zip