Главная » Spring » Внедрение не-Spring компонентов

0

Как рассказывалось в главе 2, одна из главных задач фреймворка Spring – настраивать экземпляры компонентов. Но до сих пор всегда подразумевалось одно обстоятельство: контейнер Spring может на- страивать только компоненты, экземпляры которых он создает сам. На первый взгляд может показаться странным, но это представляет некоторые проблемы. Не все объекты, имеющиеся в приложении, создаются контейнером Spring. Рассмотрим следующие возможные ситуации:

# Обычно JSP-теги реализуются веб-контейнером, в рамках ко-

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

# Доменные объекты, которые типично создаются во время вы-

полнения инструментами ORM (такими как Hibernate или iBATIS). В расширенной доменной модели доменные объекты обладают и информацией о состоянии, и поведением. Но ес- ли нет возможности внедрить служебные объекты в доменные объекты, то доменные объекты должны создавать их сами или иметь собственную реализацию логики их поведения.

Существует еще одна веская причина, почему может потребовать- ся возложить на фреймворк Spring обязанность по настройке объ-

Внедрение не-Spring компонентов

133

ектов, которых он не создает. Например, предположим, что мы явно создаем экземпляр класса Instrumentalist  из примера «Spring Idol»:

Instrumentalist   pianist   =   new   Instrumentalist(); pianist.perform();

Так как Instrumentalist – это POJO, нет никаких причин, препят- ствующих явному созданию его экземпляра. Но когда вызывается метод perform(), может возникнуть исключение NullPointerException, потому что, несмотря на отсутствие препятствий непосредственного создания экземпляра класса Instrumentalist, его свойство instrument может иметь значение null.

Естественно,  можно  вручную  настроить  свойства  объекта

Instrumentalist. Например:

Piano  piano  =  new  Piano(); pianist.setInstrument(piano); pianist.setSong("Chopsticks");

Даже при том, что вручную настроенные свойства будут работать, такой подход лишает преимущества отделения настроек от про- граммного кода. Кроме того, если бы экземпляры класса Instrumen- talist создавались механизмом ORM, мы бы не смогли изменять настройки их свойств.

К счастью, в версии Spring 2.0 появилась возможность деклара- тивно настраивать компоненты, экземпляры которых создаются за пределами Spring. Суть в том, что Spring настраивает компоненты, но не создает их экземпляры.

Рассмотрим компонент  Instrumentalist,  явно  созданный  выше. В идеале хотелось бы сконфигурировать компонент pianist за преде- лами программного кода и позволить фреймворку Spring внедрить значения в его свойства instrument и song. Следующий фрагмент XML-кода демонстрирует, как этого добиться.

<bean  id="pianist"

class="com.springinaction.springidol.Instrumentalist"

abstract="true">

<property name="song" value="Chopsticks" />

<property name="instrument">

<bean  class="com.springinaction.springidol.Piano"  />

</property>

</bean>

В таком объявлении компонента нет ничего необычного. Ком- понент pianist объявляется как объект класса Instrumentalist. А его свойства song и instrument связываются со своими значениями. Это самый заурядный компонент Spring, за исключением одной малень- кой детали: его атрибут abstract имеет значение true.

Как рассказывалось выше, атрибут abstract со значением true со- общает фреймворку Spring, что для этого компонента не требуется создавать экземпляр класса. Этот прием часто используется при объявлении родительских компонентов, которые будут расширяться дочерними компонентами. Но в данном случае мы просто указываем фреймворку Spring, что компонент pianist не должен создаваться им, – это будет сделано без участия фреймворка.

На самом деле компонент pianist служит для Spring лишь шаб- лоном настройки экземпляров Instrumentalist, созданных за его пре- делами. После определения шаблона необходим некоторый способ связывания его с классом Instrumentalist. Для этого нужно анноти- ровать класс Instrumentalist аннотацией @Configurable:

package com.springinaction.springidol;

import    org.springframework.beans.factory.annotation.Configurable;

@Configurable("pianist")

public  class  Instrumentalist  implements  Performer  {

}

Аннотация @Configurable играет двоякую роль:

# во-первых, она показывает, что экземпляр класса Instrumentalist может быть сконфигурирован фреймворком Spring, даже при создании за его пределами;

# она также связывает класс Instrumentalist и компонент с иден- тификатором pianist. При настройке экземпляра класса Instru- mentalist фреймворк Spring будет использовать определение компонента pianist как шаблон.

Но как Spring узнает, как настраивать компоненты с аннотацией

@Configurable? За это отвечает следующий элемент в конфигурации Spring:

<aop:spring-configured  />

Элемент <aop:spring-configured> – это один из множества новых элементов, появившихся в Spring 2.0. Они подсказывают фреймвор-

ку Spring, что эти компоненты необходимо конфигурировать, даже если они созданы где-то в другом месте.

За кулисами элемент <aop:spring-configured> устанавливает аспект AspectJ с точкой внедрения, которая срабатывает при создании лю- бого компонента с аннотацией @Configurable. Сразу после создания компонента в игру вступает аспект и внедряет свойства в новый экземпляр, опираясь на шаблон <bean> в конфигурации Spring.

Так как аспект, сконфигурированный фреймворком Spring, явля- ется аспектом AspectJ, приложение должно запускаться под управ- лением JVM с включенной поддержкой AspectJ. Проще всего вклю- чить эту поддержку в Java 5 JVM – это запустить ее со следующим аргументом JVM:

-javaagent:/path/to/aspectjweaver.jar

Фактически этот аргумент предписывает виртуальной машине JVM выполнить внедрение любых аспектов AspectJ на этапе загруз- ки. Для этого она должна знать, где находятся классы AspectJ. Вам потребуется заменить

/path/to/aspectjweaver.jar

действительным путем к файлу aspectjweaver.jar  в вашей системе (если, конечно, он не находится в каталоге /path/to).

Чтобы продемонстрировать способность фреймворка Spring кон- фигурировать компоненты, созданные за его пределами, в этом раз- деле явно был создан экземпляр Instrumentalist. Тем не менее, как уже упоминалось выше, в действующих приложениях подобные конфигурируемые компоненты, вероятнее всего, будут создаваться механизмом ORM или некоторой сторонней библиотекой.

А теперь рассмотрим, как редактор свойств фреймворка Spring выполняет простую работу по внедрению сложных значений, опи- раясь на строковое представление.

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

По теме:

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