В данной главе рассматривается реализация в Spring Framework принципа инверсии контроля (Inversion of Control, IoC). IoC также известен как внедрение зависимостей (DI). Это процесс, при котором объекты определяют свои зависимости (то есть другие объекты, с которыми они работают) только через аргументы конструктора, аргументы фабричного метода или свойства, которые устанавливаются на экземпляр объекта после его создания или возврата фабричным методом. Затем контейнер внедряет эти зависимости при создании бина. Данный процесс по своей сути является инверсией (отсюда и название, инверсия контроля (Inversion of Control)) самого бина, самостоятельно контролирующего создание или размещение его зависимостей с помощью прямого построения классов или такого механизма, как шаблон локатора служб (Service Locator).

Пакеты org.springframework.beans и org.springframework.context являются основой для IoC-контейнера Spring Framework. Интерфейс BeanFactory предоставляет расширенный механизм конфигурации, способный управлять объектами любого типа. ApplicationContext является подинтерфейсом BeanFactory. В нем добавляются:

  • Более простая интеграция с функциями АОП в Spring

  • Обработка ресурсов сообщений (для использования в интернационализации)

  • Публикация событий

  • Контексты, специфичные для уровня приложений, такие как WebApplicationContext для использования в веб-приложениях.

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

В Spring объекты, которые составляют основу вашего приложения и управляются IoC-контейнером Spring, называются бинами (beans). Бин (bean) - это объект, который создается, компонуется и управляется IoC-контейнером Spring. В ином случае бин - это просто один из многих объектов в вашем приложении. Бины и зависимости между ними отражены в конфигурационных метаданных, используемых контейнером.

Кратко о контейнерах

Интерфейс org.springframework.context.ApplicationContext представляет IoC-контейнер Spring и отвечает за создание экземпляра, настройку и компонование бинов. Контейнер получает инструкции о том, какие объекты создавать, конфигурировать и компоновать путем считывания конфигурационных метаданных. Конфигурационные метаданные представлены в виде XML, аннотаций Java или кода Java. Это позволяет выражать объекты, составляющие приложение, и богатую взаимозависимость между этими объектами.

Несколько реализаций интерфейса ApplicationContext поставляются вместе с Spring. В автономных приложениях обычно создается экземпляр ClassPathXmlApplicationContext или FileSystemXmlApplicationContext. Хотя XML является традиционным форматом для определения конфигурационных метаданных, можно указать контейнеру использовать аннотации Java или код в качестве формата метаданных, предоставив небольшой объем конфигурации XML для декларативного включения поддержки этих дополнительных форматов метаданных.

В большинстве сценариев применения четкий пользовательский код не требуется для создания одного или нескольких экземпляров IoC-контейнера Spring. Например, в сценарии веб-приложения обычно достаточно восьми (или около того) строк шаблона веб-дескриптора XML в файле web.xml приложения. Если вы используете Spring Tools для Eclipse (среда разработки на базе Eclipse), то можете легко создать эту стандартную конфигурацию несколькими щелчками мыши или нажатиями клавиш.

На схеме ниже изображено высокоуровневое представление того, как работает Spring. Классы приложения объединяются с конфигурационными метаданными таким образом, что после создания и инициализации ApplicationContext вы получаете полностью сконфигурированную и исполняемую систему или приложение.

Конфигурационные метаданные

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

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

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

Для получения информации об использовании других форм метаданных с контейнером Spring см раздел:

  • Конфигурация на основе аннотаций: В Spring 2.5 появилась поддержка конфигурационных метаданных на основе аннотаций.: Spring 2.5 introduced support for annotation-based configuration metadata.

  • Конфигурация на основе Java: Начиная со Spring 3.0, многие функции, предоставляемые проектом Spring JavaConfig, стали частью ядра Spring Framework. Таким образом, можно определять бины, которые являются внешними по отношению к классам вашего приложения, используя Java, а не XML-файлы. Чтобы использовать эти новые функции, обратитесь к аннотациям @Configuration, @Bean, @Import и @DependsOn.

Конфигурация Spring состоит минимум из одного, но, как правило, все же более чем одного определения бина, которыми контейнер должен управлять. Конфигурационные метаданные на основе XML настраивают эти бины как элементы <bean/> внутри элемента <bean/> верхнего уровня. В конфигурации Java обычно используются методы с описанием @Bean в классе @Configuration.

Эти определения бинов соответствуют фактическим объектам, из которых состоит ваше приложение. Как правило, вы определяете объекты уровня служб, объекты доступа к данным (DAO), объекты представления, такие как экземпляры Struts Action, объекты инфраструктуры, такие как Hibernate SessionFactories, JMS Queues и так далее. Как правило, детализированные объекты домена в контейнере не настраиваются, поскольку за создание и загрузку объектов домена обычно отвечают DAO и бизнес-логика. Однако вы можете использовать интеграцию Spring с AspectJ для конфигурирования объектов, которые были созданы вне контроля IoC-контейнера.

В следующем примере показана базовая структура конфигурационных метаданных на основе XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="..." class="...">  
        <!-- взаимодействующие объекты (collaborators) и конфигурация для этого бина находятся здесь -->
    </bean>
    <bean id="..." class="...">
        <!-- взаимодействующие объекты (collaborators) и конфигурация для этого бина находятся здесь -->
    </bean>
    <!-- еще определения бинов смотрите здесь -->
</beans>
  1. Атрибут id - это строка, которая идентифицирует определение отдельного бина.
  2. Атрибут class определяет тип бина и использует полное имя класса.

Значение атрибута id относится к взаимодействующим объектам. XML для ссылки на взаимодействующие объекты в этом примере не показан.