В этом уроке мы увидим, как мы можем избежать неоднозначности программных зависимостей при внедрении компонентов Java EE CDI. Мы уже показали в примере устранения неоднозначности зависимостей Jave EE, как избежать устранения неоднозначности зависимостей в компонентах CDI. Здесь мы покажем вам, как избежать двусмысленности зависимостей динамическим способом. Мы добьемся этого, проверив точку внедрения компонента, который внедряет реализацию другого компонента.
Программная неоднозначность с проверкой точки впрыска будет исследована путем создания простого сервиса с двумя реализациями. Затем мы создадим метод Producer для создания и внедрения обеих реализаций в приложении.
Нашей предпочтительной средой разработки является Eclipse . Мы используем версию Eclipse Juno (4.2) вместе с плагином Maven Integration версии 3.1.0. Вы можете скачать Eclipse отсюда и Maven Plugin для Eclipse отсюда . Установка плагина Maven для Eclipse выходит за рамки данного руководства и не будет обсуждаться. Tomcat 7 — это используемый сервер приложений.
Давайте начнем,
1. Создайте новый проект Maven
Перейдите в Файл -> Проект -> Maven -> Проект Maven.
На странице мастера «Выберите имя проекта и местоположение» убедитесь, что опция «Создать простой проект (пропустить выбор архетипа») не отмечена , нажмите «Далее», чтобы продолжить со значениями по умолчанию.
Здесь должен быть добавлен архетип maven для создания веб-приложения. Нажмите «Добавить архетип» и добавьте архетип. Установите переменную «Archetype Group Id» на "org.apache.maven.archetypes" , переменную «Archetype ardact Id» на "maven-archetype-webapp" и «Archetype Version» на "1.0" . Нажмите «ОК», чтобы продолжить.
На странице мастера «Введите идентификатор артефакта» вы можете определить имя и основной пакет вашего проекта. Установите для переменной «Group Id» значение "com.javacodegeeks.snippets.enterprise" а для переменной «Artifact Id» — "cdibeans" . Вышеупомянутые варианты составляют основной пакет проекта как "com.javacodegeeks.snippets.enterprise.cdibeans" а имя проекта — "cdibeans" . Установите для переменной «Package» значение "war" , чтобы создать файл war для развертывания на сервере tomcat. Нажмите «Готово», чтобы выйти из мастера и создать свой проект.
Структура проекта Maven показана ниже:
- Он состоит из следующих папок:
- Папка / 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
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <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> <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!!!"); }} |
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. Создайте метод Producer для внедрения компонента
Чтобы добавить сервис другому бину, мы создаем собственную аннотацию. CDI позволяет нам создавать нашу собственную аннотацию Java, то есть GreetingType.java , а затем использовать ее в точке внедрения нашего приложения, чтобы получить правильную реализацию GreetingCard соответствии с GreetingType компонента.
Greetings — это перечисление, параметризованное реализациями службы, как показано ниже:
GreetingType.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
|
package com.javacodegeeks.snippets.enterprise.cdibeans;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.ElementType.TYPE;import static java.lang.annotation.RetentionPolicy.RUNTIME;import java.lang.annotation.Retention;import java.lang.annotation.Target;import com.javacodegeeks.snippets.enterprise.cdibeans.impl.AnotherGreetingCardImpl;import com.javacodegeeks.snippets.enterprise.cdibeans.impl.GreetingCardImpl;@Retention(RUNTIME)@Target({ FIELD, TYPE, METHOD })public @interface GreetingType { Greetings value(); public enum Greetings { HELLO(GreetingCardImpl.class), HI(AnotherGreetingCardImpl.class); Class<? extends GreetingCard> clazz; private Greetings(Class<? extends GreetingCard> clazz){ this.clazz = clazz; } public Class<? extends GreetingCard> getClazz() { return clazz; } }} |
Теперь мы можем создать Producer для предоставления приложениям экземпляров реализаций службы GreetingCard . Класс GreetingCardFactory.java является источником, у которого есть метод getGreetingCard . Метод принимает два параметра. Первый параметр — это javax.enterprise.inject.Instance параметризованный с требуемым типом бина, то есть здесь GreetingCard . Он аннотируется аннотацией @Any которая позволяет точке внедрения ссылаться на все bean-компоненты или все события определенного типа bean-компонента. Второй параметр — это javax.enterprise.inject.spi.InjectionPoint который является полем в клиентском приложении, которое будет вводить компонент с @Inject аннотации @Inject . Таким образом, метод вернет правильную реализацию сервиса в соответствии с типом сервиса и аннотациями в точке внедрения.
GreetingCardFactory.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
package com.javacodegeeks.snippets.enterprise.cdibeans;import javax.enterprise.inject.Any;import javax.enterprise.inject.Instance;import javax.enterprise.inject.Produces;import javax.enterprise.inject.spi.Annotated;import javax.enterprise.inject.spi.InjectionPoint;public class GreetingCardFactory { @Produces @GreetingsProducer public GreetingCard getGreetingCard(@Any Instance<GreetingCard> instance, InjectionPoint ip){ Annotated gtAnnotated = ip.getAnnotated(); GreetingType gtAnnotation = gtAnnotated.getAnnotation(GreetingType.class); Class<? extends GreetingCard> greetingCard = gtAnnotation.value().getClazz(); return instance.select(greetingCard).get(); }} |
Обратите внимание, что метод @Produces дополнительной аннотацией, кроме аннотации @Produces которая определяет метод как источник. Аннотация @GreetingsProducer используется для точки внедрения, чтобы определить, что она использует указанный метод Producer для внедрения экземпляра компонента. Это фактически CDI Qualifier, показанный ниже:
GreetingsProducer.java
|
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
package com.javacodegeeks.snippets.enterprise.cdibeans;import static java.lang.annotation.ElementType.FIELD;import static java.lang.annotation.ElementType.METHOD;import static java.lang.annotation.ElementType.TYPE;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 GreetingsProducer {} |
5. Запустите приложение
Чтобы запустить приложение, мы создали простой сервлет.
В сервлете ниже обе реализации внедрены. Каждая точка внедрения в сервлете является полем, в котором @Inject аннотация @Inject . Он также аннотируется аннотацией @GreetingsProducer для указания источника, который будет использоваться, а также аннотацией @GreetingType , указывающей, какая реализация будет произведена источником.
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
45
46
47
|
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.GreetingType.Greetings;import com.javacodegeeks.snippets.enterprise.cdibeans.GreetingsProducer;@WebServlet(name = "greetingServlet", urlPatterns = {"/sayHello"})public class GreetingServlet extends HttpServlet { private static final long serialVersionUID = 2280890757609124481L; @Inject @GreetingsProducer @GreetingType(Greetings.HELLO) private GreetingCard greetingCard; @Inject @GreetingsProducer @GreetingType(Greetings.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
и результат показан ниже:
Это было учебное руководство по устранению неоднозначности программных зависимостей CDI Java EE с проверкой точки внедрения
Загрузите исходный код этого учебника: CDIDependencyDisambiguationIPInspection.zip





