Главная » Spring » Внедрение объектов из JNDI Spring

0

Конфигурационное пространство имен jee в Spring обеспечивает возможность работы с JNDI способом, не создающим тесной зависи- мости. Внутри этого пространства имен имеется элемент <jee:jndi- lookup>, который упрощает внедрение объектов из JNDI в Spring.

Для иллюстрации вернемся к примеру из главы 6. Там элемент

<jee:jndi-lookup> использовался для извлечения объекта DataSource из JNDI:

<jee:jndi-lookup  id="dataSource"

jndi-name="/jdbc/SpitterDS" resource-ref="true"  />

Атрибут jndi-name определяет имя объекта в репозитории JNDI. Это имя используется по умолчанию для поиска объекта в JNDI. Но если поиск выполняется в контейнере Java EE, тогда может по- требоваться добавить префикс java:comp/env/. Этот префикс можно добавить вручную, при определении значения в атрибуте jndi-name. Однако если указать в атрибуте resource-ref значение true, то же самое будет выполнено элементом  <jee:jndi-lookup>  автоматически.

Объявив компонент dataSource, его можно внедрить в свойство dataSource. Например, его можно использовать для настройки фаб- рики сеансов Hibernate:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.

➥   AnnotationSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

</bean>

Как показано на рис. 17.3, когда фреймворк Spring будет связы- вать компонент sessionFactory, он внедрит объект DataSource, полу- ченный из JNDI, в свойство dataSource фабрики сеансов.

Рис. 17.3. Элемент <jee:jndi-lookup> извлекает объект из JNDI, превращая его в компонент в контексте приложения Spring. После этого его можно внедрить в любой другой объект

Вся прелесть использования элемента <jee:jndi-lookup> для из- влечения объекта из JNDI – в том, что единственным фрагментом кода, который знает, что объект DataSource извлекается из JNDI, яв- ляется объявление компонента dataSource в XML-файле. Компонент sessionFactory понятия не имеет (и его это не интересует), откуда по- лучен объект DataSource. А это означает, что если вы решите получить объект DataSource из драйвера JDBC, достаточно будет просто пере- определить компонент dataSource, указав класс DriverManagerDataSource.

Теперь источник данных будет извлекаться из репозитория JNDI и внедряться в фабрику сеансов. Мы избавились от реализации по- иска объекта в JNDI! Всякий раз, когда нам потребуется источник данных, мы сможем получить его в виде компонента dataSource из контекста приложения Spring.

Как было показано выше, внедрение компонентов, хранящихся в JNDI, в Spring реализуется очень просто. А теперь познакомимся с несколькими способами влиять на то, когда и как объект должен извлекаться из JNDI, начав с кеширования.

Кеширование объектов из JNDI

Часто объекты, извлекаемые из репозитория JNDI, используются многократно. Источник данных, например, будет необходим всякий раз, когда потребуется выполнить обращение к базе данных. Было бы слишком расточительно извлекать источник данных из JNDI каждый раз, когда появится нужда в нем. По этой причине элемент

<jee:jndi-lookup>  по умолчанию кеширует объекты, полученные из JNDI.

Кеширование отлично подходит для большинства ситуаций. Но препятствует «горячей» реорганизации объектов в JNDI. Если вам понадобится изменить объект в JNDI, это повлечет за собой необ- ходимость перезапустить приложение Spring, чтобы оно извлекло новый объект.

Если предполагается, что извлекаемый приложением объект бу- дет часто изменяться, кеширование желательно отключить в элемен- те <jee:jndi-lookup>. Для этого нужно указать значение false в атри- буте cache:

<jee:jndi-lookup  id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true" cache="false"

proxy-interface="javax.sql.DataSource"   />

Значение false в атрибуте cache сообщает элементу <jee:jndi- lookup>, что объект всегда должен извлекаться из репозитория JNDI. Обратите внимание, что при этом также был определен атрибут proxy-interface. Поскольку объект в JNDI может измениться в лю- бой момент, элемент <jee:jndi-lookup> не имеет никакой возможности узнать фактический тип объекта. Атрибут proxy-interface указывает ожидаемый тип извлекаемого объекта.

Отложенная загрузка объектов из JNDI

Иногда приложению не требуется извлекать объект из JNDI не- медленно. Например, представьте, что объект из JNDI используется только при определенных условиях. В этой ситуации может ока-

заться нежелательным загружать объект до того момента, когда он действительно будет необходим.

По умолчанию элемент <jee:jndi-lookup> извлекает объекты из JNDI в момент запуска контекста приложения. Однако имеется воз- можность отсрочить загрузку объекта до момента, когда он станет необходим, определив в атрибуте lookup-on-startup  значение false:

<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true"

lookup-on-startup="false"

proxy-interface="javax.sql.DataSource"   />

Как и в случае с атрибутом cache, при установке значения false в атрибуте lookup-on-startup необходимо определить атрибут proxy- interface. Это обусловлено тем, что элемент <jee:jndi-lookup> не зна- ет тип извлекаемого объекта, пока действительно не извлечет его. Атрибут proxy-interface  сообщает ему ожидаемый тип объекта.

Запасные объекты на случай неудачи

Теперь вы знаете, как внедрять объекты из репозитория JNDI. Жизнь прекрасна. Но что, если объект не будет найден в JNDI?

Например, приложение может рассчитывать получить источник данных из JNDI при выполнении в промышленном окружении. Но на этапе разработки это может оказаться невозможным. Если при- ложение будет настроено на получение источника данных из репо- зитория JNDI на этапе эксплуатации, то на этапе разработки загруз- ка объекта будет терпеть неудачу. Как тогда обеспечить извлечение компонента источника данных из JNDI на этапе эксплуатации и явно настраивать его на этапе разработки?

Как было показано выше, элемент <jee:jndi-lookup> прекрасно справляется с извлечением объектов из JNDI и их внедрением в контекст приложения Spring. Но он также имеет аварийный ме- ханизм на случай, когда запрашиваемый объект отсутствует в ре- позитории JNDI. Чтобы задействовать его, необходимо настроить атрибут   default-ref.

Например, допустим, что источник данных в конфигурации Spring объявляется как компонент класса DriverManagerDataSource:

<bean id="devDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"

lazy-init="true">

<property   name="driverClassName"

value="org.hsqldb.jdbcDriver"  />

<property  name="url"

value="jdbc:hsqldb:hsql://localhost/spitter/spitter"   />

<property name="username" value="sa" />

<property name="password" value="" />

</bean>

Этот источник данных будет использоваться на этапе разработки. Но на этапе разработки должен использоваться источник данных из JNDI, настраиваемый системным администратором. В этом случае элемент <jee:jndi-lookup> мог бы быть настроен, как показано ниже:

<jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true"

default-ref="devDataSource" />

Здесь в атрибут default-ref записывается ссылка на компонент devDataSource. Если элемент <jee:jndi-lookup> не сможет получить из JNDI объект с именем jdbc/SpitterDS, он будет использовать ком- понент devDataSource. А поскольку компонент источника данных по умолчанию содержит атрибут lazy-init со значением true, он не бу- дет создан, пока действительно не понадобится.

Как видите, элемент <jee:jndi-lookup> существенно упрощает внед- рение объектов из JNDI в контекст приложения Spring. Однако, как оказывается, элемент <jee:jndi-lookup> также может использоваться для внедрения компонентов сеансов EJB. Посмотрим, как это сделать.

Источник:   Уоллс К., Spring в действии. – М.: ДМК Пресс, 2013. – 752 с.: ил.

По теме:

  • Комментарии