Главная » Spring » Специальные компоненты Spring

0

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

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

конфигурации компонента;

# загружать информацию о конфигурации из внешних файлов;

# загружать текстовые сообщения из файлов, включая интерна- ционализированные сообщения;

# принимать и реагировать на события в приложении, опубли-

кованные другими компонентами и самим контейнером Spring;

# определять их идентичность в рамках контейнера Spring.

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

Начнем изучение специализированных компонентов Spring с пост- обработки других компонентов после их связывания.

Компоненты постобработки

В главе 1 было продемонстрировано, как определять компоненты в пределах контейнера Spring и как их связывать. Чаще всего нет оснований ожидать, что компоненты будут связаны как-то иначе,

чем определено в XML-файле. XML-файл воспринимается как ис- точник информации о настройках объектов приложения.

Но, как видно на рис. 1.5, фреймворк Spring предлагает две воз-

можности включиться в управление жизненным циклом компонен- та и просмотреть или изменить его конфигурацию. Это называется постобработкой. Из названия можно сделать предположение, что это некая обработка, выполняемая после некоторых событий. Со- бытие постобработки следует за событиями создания и настройки компонента. Интерфейс BeanPostProcessor предоставляет две возмож- ности изменить компонент после его создания и связывания:

public  interface  BeanPostProcessor  {

Object  postProcessBeforeInitialization(

Object  bean,  String  name)  throws  BeansException;

Object  postProcessAfterInitialization(

Object  bean,  String  name)  throws  BeansException;

}

Метод  postProcessBeforeInitialization()  вызывается  непосред- ственно перед инициализацией компонента (перед вызовом мето- да afterPropertiesSet() и метода, указанного в атрибуте init-method). Аналогично метод  postProcessAfterInitialization()  вызывается  сразу же после инициализации.

Постпроцессор   компонентов

Предположим, для примера, что необходимо изменить все стро- ковые свойства компонентов приложения с целью перевести их на язык Элмера Фудда (Elmer Fudd)1. Класс Fuddifier, представленный в листинге 3.5, – это реализация интерфейса BeanPostProcessor, кото- рая выполняет именно это действие.

Листинг 3.5. Преобразование строковых свойств с использованием BeanPostProcessor

public class Fuddifier implements BeanPostProcessor { public  Object  postProcessAfterInitialization(

1 Когда все буквы R и L в словах замещаются буквой W. Чтобы получить представление, как это может выглядеть, попробуйте в словах русского языка заменить буквы Р и Л буквой В. Элмер Фудд (яйцеголовый) – мультипликационный герой, заклятый враг кролика Багс Банни (Bugs Bunny). – Прим. перев.

Object bean, String name) throws BeansException { Field[]   fields   =   bean.getClass().getDeclaredFields();

try  {

for(int i=0; i < fields.length; i++) {   // Преобразует все if(fields[i].getType().equals(              // строковые свойства

java.lang.String.class)) {              // компонентов fields[i].setAccessible(true);

String   original   =   (String)   fields[i].get(bean); fields[i].set(bean,       fuddify(original));

}

}

}  catch  (IllegalAccessException  e)  { e.printStackTrace();

}

return bean;

}

private String fuddify(String orig) {  // Преобразует все строковые if(orig == null) return orig;          // свойства компонентов return   orig.replaceAll("(r|l)",   "w")

.replaceAll("(R|L)", "W");

}

public Object postProcessBeforeInitialization(              // Перед инициализацией Object bean, String name) throws BeansException { // ничего

return  bean;                                                                  // не  делает

}

}

Метод postProcessAfterInitialization() выполняет в  цикле  итера- ции по всем свойствам компонента, выбирая свойства, имеющие тип java.lang.String. Каждое строковое свойство передается мето- ду fuddify(), преобразующему строку на язык Фудда. В результате в свойстве сохраняется «фуддифицированная» строка текста (об- ратите внимание также на вызов метода setAccessible() для каждого свойства, который используется здесь с целью обойти правила ви- димости частных свойств; это нарушает принцип инкапсуляции, но иначе эти свойства останутся недоступны).

Метод postProcessBeforeInitialization() специально оставлен бес- полезным – он просто возвращает компонент в неизменном виде. На самом деле «фуддификацию» строковых свойств можно было бы выполнить в этом методе.

Теперь, когда у нас есть постпроцессор BeanPostProcessor, выполняю- щий преобразование строковых свойств, посмотрим, как сообщить контейнеру, чтобы он применил его ко всем компонентам.

Регистрация постпроцессора компонентов

Если приложение выполняется в рамках фабрики компонентов, каждый постпроцессор BeanPostProcessor придется регистрировать программно, с помощью метода addBeanPostProcessor() фабрики:

BeanPostProcessor   fuddifier   =   new   Fuddifier(); factory.addBeanPostProcessor(fuddifier);

Более вероятно, однако, что вы предпочтете использовать кон- текст приложения. В этом случае достаточно просто зарегистриро- вать постпроцессор как компонент внутри контекста.

<bean

class="com.springinaction.chapter03.postprocessor.Fuddifier"/>

Контейнер опознает компонент fuddifier как реализацию интер- фейса BeanPostProcessor и будет вызывать его методы постобработки до и после инициализации каждого компонента.

В результате регистрации компонента fuddifier все строковые свойства всех компонентов будут «фуддифицированы». Например, допустим, что имеется следующее определение компонента:

<bean  id="bugs"  class="com.springinaction.chapter03.postprocessor.Rabbit">

<property  name="description"  value="That  rascally  rabbit!"  />

</bean>

Когда постпроцессор fuddifier  завершит обработку, свойство

description  будет содержать строку «That wascawwy wabbit!»1.

Собственные постпроцессоры фреймворка Spring

Фреймворк Spring Framework сам использует несколько реализа- ций интерфейса BeanPostProcessor. Например, ApplicationContextAwarePr ocessor, устанавливающий контекст приложения в компонентах, реа- лизующих интерфейс ApplicationContextAware  (см. раздел 3.5.6). Его

1   Или на русском языке: «Этот подлый кролик!» – «Этот подвый кво- вик!» – Прим. перев.

не нужно регистрировать, он будет зарегистрирован автоматически, контекстом приложения.

В главе 5 будет показана другая реализация интерфейса BeanPost- Processor.

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

По теме:

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