Главная » Spring » Автоматическое  связываниес применением стандартной аннотации@Inject Spring

0

С целью унификации модели программирования для применения в различных фреймворках, реализующих внедрение зависимостей, организация Java Community Process недавно опубликовала специ- фикацию «Dependency Injection for Java». Известная в организации Java Community Process под названием JSR-330, эта спецификация описывает обобщенную модель внедрения зависимостей в языке

Java. Эта модель поддерживается фреймворком Spring, начиная с версии Spring 3.01.

Центральное положение в модели JSR-330 занимает аннотация

@Inject. Эта аннотация является практически полным аналогом ан- нотации @Autowired фреймворка Spring. Поэтому вместо аннотации

@Autowired для описания свойства instrument можно использовать ан- нотацию @Inject:

@Inject

private Instrument instrument;

Как и @Autowired, аннотацию @Inject можно использовать для ав- томатического связывания свойств, методов и конструкторов. В от- личие от @Autowired, аннотация @Inject не имеет атрибута required. Поэтому неудовлетворенные зависимости, описываемые аннотацией

@Inject, будут приводить к исключению.

В дополнение к аннотации @Inject в модели JSR-330 предусмотре- на еще одна хитрость. Вместо того чтобы внедрять зависимости не- посредственно, от аннотации @Inject можно потребовать, чтобы она внедряла ссылку на реализацию интерфейса Provider. Среди всего прочего интерфейс Provider обеспечивает возможность отложенного внедрения ссылок на компоненты и внедрение нескольких экземп- ляров компонента.

Например, представьте, что имеется класс KnifeJuggler (жонглер ножами), в экземпляр которого должен быть внедрен один или бо- лее экземпляров класса Knife (нож). Предположим, что компонент типа Knife объявлен как имеющий область действия prototype, тогда следующий конструктор KnifeJuggler  сможет получить пять компо- нентов типа Knife:

private  Set<Knife>  knives;

@Inject

public   KnifeJuggler(Provider<Knife>   knifeProvider)   { knives = new HashSet<Knife>();

for  (int  i =  0;  i <  5;  i++)  { knives.add(knifeProvider.get());

}

}

1 Фреймворк Spring – не единственный, поддерживающий JSR-330. Мо- дель JSR-330 также поддерживается фреймворками Google Guice и Pico- container.

Вместо экземпляров класса Knife  на этапе конструирования эк- земпляр KnifeJuggler получит экземпляр Provider<Knife>. На  этом этапе будет внедрен только экземпляр объекта-посредника Provider. Внедрение фактических объектов типа Knife будет отложено до вы- зова метода get() объекта-посредника. В данном случае метод get() вызывается пять раз. А поскольку компонент типа Knife имеет об- ласть действия prototype, во множестве knives будет сохранено пять различных объектов типа Knife.

Уточнение связываемых свойств

Как видите, аннотации @Inject и @Autowired имеют много общего. И подобно @Autowired, аннотация @Inject также подвержена пробле- ме неоднозначности выбора компонента для внедрения. Аннотация

@Inject тоже может сопровождаться уточняющей аннотацией @Named, подобной аннотации @Qualifier.

Аннотация @Named действует подобно аннотации @Qualifier, как по- казано ниже:

@Inject

@Named("guitar")

private Instrument instrument;

Важным отличием аннотации @Qualifier, определяемой фрейм- ворком Spring, от аннотации @Named, определяемой спецификацией JSR-330, является семантика их использования. Аннотация @Quali- fier помогает сузить круг компонентов, доступных для выбора (ис- пользуя идентификатор компонента как один из возможных ква- лификаторов), тогда как аннотация @Named однозначно ссылается на идентификаторы   компонентов.

Создание собственных квалификаторов JSR-330

Как оказывается, спецификация JSR-330 определяет собствен- ную аннотацию @Qualifier в пакете javax.inject. В отличие от ан- нотации @Qualifier, определяемой фреймворком Spring, версия JSR-330 не имеет самостоятельного значения. Она предназначена для определения пользовательских аннотаций-квалификаторов, почти так же, как аннотация @Qualifier, определяемая фреймвор- ком Spring1.

1  В действительности аннотация @Named сама определена посредством ан- нотации @Qualifier.

Например, следующий листинг демонстрирует определение но- вой аннотации @StringedInstrument, созданной с помощью аннотации

@Qualifier, определяемой спецификацией JSR-330.

Листинг 4.2. Создание собственного квалификатора с помощью аннотации @Qualifier, определяемой спецификацией JSR-330

package   com.springinaction.springidol; import  java.lang.annotation.ElementType; import    java.lang.annotation.Retention; import     java.lang.annotation.RetentionPolicy; import     java.lang.annotation.Target;

import javax.inject.Qualifier;

@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Qualifier

public  @interface  StringedInstrument  {

}

Как видите, единственное отличие между листингами 4.2 и 4.1 заключается в инструкции импортирования определения аннота- ции @Qualifier. В листинге 4.1 использовалось определение из па- кета org.springframework.beans.factory.annotation. А в этом примере была задействовано определение стандартной аннотации @Qualifier из пакета javax.inject. Во всем остальном примеры совершенно идентичны.

Автоматическое связывание на основе аннотаций отлично подхо- дит для внедрения ссылок на компоненты и избавления от лишних элементов <property> в XML-файле конфигурации Spring. Но можно ли использовать аннотации для внедрения строковых и других прос- тых значений в свойства?

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

По теме:

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