Статьи

Учебник по внедрению зависимостей CDI для Java EE (@Inject)

В этом руководстве мы покажем вам, как добиться внедрения зависимостей в управляемых компонентах CDI. В частности, мы будем использовать аннотацию @Inject предоставляемую API-интерфейсом CDI, чтобы внедрить компонент CDI в другой компонент. Таким образом, компонент может использоваться в приложении, таком как приложение JavaServer Faces.

CDI предоставляет несколько способов внедрить bean-компонент в приложение. Мы можем внедрить bean-компонент CDI, используя Инъекцию Зависимости Поля, Инъекцию Зависимости Конструктора или Инъекцию Зависимости через метод установки. Мы также можем вводить аргументы методов-производителей, но это выходит за рамки данного руководства. Давайте рассмотрим все способы введения, предоставляемые CDI:

1. Инъекция зависимости от поля

Самый простой способ внедрить bean-компонент CDI — добавить аннотацию @Inject в свойство для @Inject . Давайте посмотрим на пример ниже. GreetingBean имеет аннотированное поле @Inject , которое является helloBean . Таким образом, другой компонент, HelloBean , внедряется в GreetingBean .

01
02
03
04
05
06
07
08
09
10
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import javax.inject.Inject;
 
public class GreetingBean {
 
    @Inject
    private HelloBean helloBean;
     
}

2. Внедрение зависимостей в конструктор

Когда компонент CDI инициализируется, контейнер будет использовать конструктор по умолчанию. Когда есть другой конструктор, аннотированный аннотацией @Inject , контейнер будет автоматически использовать этот конструктор, и таким образом аргумент, переданный в конструкторе, будет введен в bean-компонент. Здесь следует отметить, что у нас может быть только одна точка инжекции конструктора. Если мы создадим еще @Inject аннотированный конструктор @Inject , поведение контейнера будет непредсказуемым.

В приведенном ниже фрагменте кода GreetingBean имеет конструктор, аннотированный аннотацией @Inject и аргументом, то есть другим компонентом HelloBean . Таким образом, инъекция достигается.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import javax.inject.Inject;
 
public class GreetingBean {
 
     private final HelloBean helloBean;
 
      @Inject
      public GreetingBean(HelloBean helloBean){
        this.helloBean = helloBean;
      }
 
}

3. Внедрение зависимостей через метод установки

В приведенном ниже примере метод setHelloBean(HelloBean helloBean) аннотируется аннотацией @Inject . Таким образом, когда GreetingBean инициализируется контейнером, метод будет вызван, так как он аннотирован HelloBean будет HelloBean .

01
02
03
04
05
06
07
08
09
10
11
12
13
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import javax.inject.Inject;
 
public class GreetingBean {
 
     private HelloBean helloBean;
 
     @Inject
      public void setHelloBean(HelloBean helloBean) {
        this.helloBean = helloBean;
      }
}

4. Использование классификатора @Any

@Any можно использовать, когда у нас есть несколько реализаций одного интерфейса, и мы хотим внедрить их все в другой bean-компонент. Используя эту аннотацию, контейнер внедрит все реализации указанного интерфейса. Он используется с интерфейсом javax.enterprise.inject.Instance предоставляемым API CDI, как показано в фрагменте кода ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
package com.javacodegeeks.snippets.enterprise.cdibeans;
 
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
 
public class GreetingBean {
 
    @Inject
    public void getAllBeanImplementations(@Any Instance<HelloBean> beans) {
 
        for (HelloBean helloBean : beans) {
            System.out.println(helloBean.getClass().getCanonicalName());
        }
 
    }
}

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

5. Использование прокси для реализации инъекции

Чтобы внедрить управляемый компонент в другой компонент (кроме аннотированных компонентов @Dependent ), контейнер CDI не будет передавать ссылку на сам внедренный компонент, а вместо этого будет передавать ссылку на прокси. Прокси-сервер обрабатывает все вызовы внедренного компонента прозрачно. Например, когда мы SessionScoped компонент SessionScoped компонент ApplicationScoped и многие клиенты обращаются к ApplicationScopedBean , прокси-серверы используются для обработки вызовов к внедренным компонентам. Каждый прокси может перенаправить вызов на правильный бин.

Наконец, обратите внимание, что прокси-сервер CDI создается путем расширения класса компонента и переопределения всех методов, не являющихся pivate. Примитивные типы не могут быть введены. Класс bean-компонента должен иметь не приватный конструктор по умолчанию и не должен быть финальным или иметь финальные методы.

Это было руководство по @Inject зависимостей в управляемых компонентах CDI с использованием аннотации @Inject .