Листинг 2.19 показывает утилитный класс, который создает и закрывает интерфейс JDBC. Метод createConnection берет драйвер Derby JDBC, создает соединение с определенным URL, обрабатывает исключения и возвращает открытое соединение JDBC. Это сопровождается аннотацией @Disposes.
Листинг 2.19. Производитель данных иутилизатор соединения JDBC
public class JDBCConnectionProducer {
··@Produces
··private Connection createConnection() {
····Connection conn = null;
····try {
······Class.forName("org.apache.derby.jdbc.EmbeddedDriver"). newInstance();
······conn = DriverManager.getConnection("jdbc: derby: memory: chapter02DB",

"APP", "APP");
····} catch (InstantiationException | IllegalAccessException | ClassNotFoundException) {
······e.printStackTrace();
····}
····return conn;
··}
··private void closeConnection(@Disposes Connection conn) throws SQLException {
····conn.close();
··}
}
Уничтожение может осуществляться путем сопоставления метода утилизатора, определенного тем же классом, что и метод производителя данных. Каждый метод утилизатора, сопровождаемый аннотацией @Disposes, должен иметь строго один параметр такого же типа (тут java.sql.Connection) и квалификаторы (@Default), как соответствующий тип возврата метода производителя данных (с аннотацией @Produces). Метод утилизатора (closeConnection()) вызывается автоматически по окончании контекста клиента (в листинге 2.20 — контекст @ApplicationScoped), и параметр получает объект, порожденный методом производителя данных.
Листинг 2.20. Производитель данных иутилизатор соединения JDBS
@ApplicationScoped
public class DerbyPingService {
··@Inject
··private Connection conn;
··public void ping() throws SQLException {
····conn.createStatement(). executeQuery("SELECT 1 FROM SYSIBM.SYSDUMMY1");
··}
}
Листинг 2.20 показывает, как компонент внедряет созданное соединение JDBC с аннотацией @Inject и использует его для проверки доступности базы данных Derby. Как видите, этот клиентский код не занимается всеми вспомогательными задачами по созданию и закрытию соединения JDBC либо обработке исключений. Производители данных и утилизаторы — хороший способ создания и закрытия ресурсов.
CDI имеет отношение не только к внедрению зависимостей, но и к контексту (буква С в аббревиатуре CDI означает контекст). Каждый объект, управляемый CDI, имеет строго определенные область видимости и жизненный цикл, которые связаны с конкретным контекстом. В Java область применения POJO достаточно проста: вы создаете экземпляр класса, используя ключевое слово new, и позволяете сборщику мусора избавиться от него, чтобы освободить некоторое количество памяти. При использовании CDI компонент связан с контекстом и остается в нем до тех пор, пока не будет разрушен контейнером. Удалить компонент из контекста вручную невозможно.
В то время как веб-уровень имеет четко определенные области видимости (приложение, сеанс, запрос), на уровне сервисов такого не было (см. также главу 7 о компонент-сеансах EJB с сохранением и без сохранения состояния). Ведь, когда компонент-сеансы или POJO используются в веб-приложениях, они не оповещаются о контекстах этих приложений. CDI соединил веб-уровень с уровнем сервисов с помощью содержательных областей видимости. Он определяет следующие встроенные области видимости и даже предлагает точки расширения, в которых вы можете создавать собственные области видимости.
• Область видимости приложения (@ApplicationScoped) — действует на протяжении всей работы приложения. Компонент создается только один раз на все время работы приложения и сбрасывается, когда оно закрывается. Эта область видимости полезна для утилитных или вспомогательных классов либо объектов, которые хранят данные, используемые совместно целым приложением. Однако необходимо проявить осторожность в вопросах конкурентного доступа, когда доступ к данным должен осуществляться по нескольким потокам.
• Область видимости сеанса (@SessionScoped) — действует на протяжении нескольких запросов HTTP или нескольких вызовов метода для одного пользовательского сеанса. Компонент создается на все время длительности HTTP-сеанса и сбрасывается, когда сеанс заканчивается. Эта область видимости предназначена для объектов, требуемых на протяжении сеанса, таких как пользовательские настройки или данные для входа в систему.
• Область видимости запроса (@RequestScoped) — соответствует единственному HTTP-запросу или вызову метода. Компонент создается на все время вызова метода и сбрасывается по его окончании. Он используется для классов обслуживания или связующих компонентов JSF, которые нужны только на протяжении HTTP-запроса.
Читать дальше