IoC-контейнер Spring управляет одним или несколькими бинами. Эти бины создаются с помощью конфигурационных метаданных, которые вы предоставляете контейнеру (например, в виде XML -определений <bean/>
).
В самом контейнере эти определения бинов представлены в виде объектов BeanDefinition
, которые содержат (среди прочей информации) следующие метаданные:
-
Полное имя класса с указанием пакета: как правило, это фактический класс реализации определяемого бина.
-
Элементы поведенческой конфигурации бина, которые определяют то, как бин должен вести себя в контейнере (область действия, обратные вызовы жизненного цикла и так далее).
-
Ссылки на другие бины, которые необходимы для его работы. Эти ссылки также называются взаимодействующими объектами (collaborators) или зависимостями (dependencies).
-
Другие параметры конфигурации, которые необходимо установить во вновь созданном объекте, например, предельный размер пула или количество соединений, используемых в бине, который управляет пулом соединений.
Эти метаданные преобразуются в набор свойств, которые составляют определение каждого бина. В следующей таблице описаны эти свойства:
Свойство | Объясняется в... |
---|---|
Класс |
|
Имя |
Именование бинов |
Область применения |
|
Аргументы конструктора |
|
Свойства |
|
Режим автоматического обнаружения и связывания |
Взаимодействующие объекты с автоматическим обнаружением и связыванием |
Режим отложенной инициализации |
|
Метод инициализации |
|
Метод уничтожения |
В дополнение к определениям бинов, которые содержат информацию о том, как создать конкретный бин, реализации ApplicationContext
также позволяют регистрировать существующие объекты, которые создаются вне контейнера (пользователями). Это возможно осуществить путем обращения к BeanFactory
ApplicationContext через метод getBeanFactory()
, который возвращает реализацию DefaultListableBeanFactory
. DefaultListableBeanFactory
поддерживает данную регистрацию через методы registerSingleton(..)
и registerBeanDefinition(..)
. Однако типичные приложения работают исключительно с бинами, определенными с помощью стандартных метаданных определения бинов.
Метаданные бинов и экземпляры-одиночки, предоставляемые вручную, должны быть зарегистрированы как можно скорее, чтобы контейнер мог правильно обработать их во время автоматического обнаружения и связывания и других этапов интроспекции. Хотя переопределение существующих метаданных и существующих экземпляров-одиночек и поддерживается в некоторой степени, регистрация новых бинов во время выполнения (одновременно с прямым доступом к фабрике) официально не поддерживается и может привести к исключениям одновременного доступа, несовместимому состоянию в контейнере бинов или к обоим этим исключениям.
Именование бинов
Каждый бин имеет один или несколько идентификаторов. Эти идентификаторы должны быть уникальными в пределах контейнера, в котором находится бин. Бины обычно имеют только один идентификатор. Однако, если требуется более одного, дополнительные можно считать псевдонимами.
В конфигурационных метаданных на основе XML используется атрибут id
, атрибут name
или оба для задания идентификаторов бина. Атрибут id
позволяет задать только один идентификатор. Обычно эти имена являются буквенно-цифровыми ('myBean', 'someService' и т.д.), но они могут содержать и специальные символы. Если вы хотите ввести другие псевдонимы для бина, то также можете задать их в атрибуте name
, отделив запятой (,
), точкой с запятой (;
) или пробелом. Историческая справка: в версиях до Spring 3.1 атрибут id
был определен как тип xsd:ID
, что ограничивало применение символов. Начиная с версии 3.1, он определяется как тип xsd:string
. Обратите внимание, что уникальность id
бина все еще обеспечивается контейнером, но уже не анализаторами XML.
Не нужно указывать name
или id
для бина. Если явно не задать name
или id
, контейнер сгенерирует уникальное имя для этого бина. Однако если вы хотите ссылаться на этот бин по имени, используя элемент ref
или поиск в стиле локатора служб (Service Locator), то должны указать имя. Мотивы отказа от указания имени связаны с использованием внутренних бинов и взаимодействующих объектов с автоматическим обнаружением и связыванием.
java.beans.Introspector.decapitalize
(который Spring использует здесь).Присвоение псевдонима бину вне определения бина
В самом определении бина можно указать более одного имени для бина, используя комбинацию из одного имени, указанного атрибутом id
, и любого количества других имен в атрибуте name
. Эти имена могут быть эквивалентными псевдонимами одного и того же бина и полезны в некоторых ситуациях, например, когда каждый компонент в приложении ссылается на общую зависимость, используя имя бина, специфичное для этого компонента.
Однако задание всех псевдонимов, в которых фактических определен бин, не всегда является достаточным. Иногда желательно ввести псевдоним для бина, который определен в другом месте. Это обычно имеет место в больших системах, где конфигурация разделена между каждой подсистемой, а каждая подсистема имеет свой собственный набор определений объектов. В конфигурационных метаданных на основе XML для этого можно использовать элемент <alias/>
. В следующем примере показано, как это сделать:
<alias name="fromName" alias="toName"/>
В этом случае бин (в том же контейнере) с именем fromName
- после использования этого определения псевдонима - может упоминаться как toName
.
Например, конфигурационные метаданные для подсистемы A могут ссылаться на источник данных DataSource под именем subsystemA-dataSource
. Конфигурационные метаданные для подсистемы B могут ссылаться на источник данных DataSource под именем subsystemB-dataSource
. При создании основного приложения, использующего обе эти подсистемы, основное приложение обращается к источнику данных DataSource под именем myApp-dataSource
. Чтобы все три имени ссылались на один и тот же объект, вы можете добавить следующие определения псевдонимов в конфигурационные метаданные:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>
<alias name="myApp-dataSource" alias="subsystemB-dataSource"/>
Теперь каждый компонент и основное приложение могут обращаться к dataSource через имя, которое является уникальным и гарантированно не будет конфликтовать ни с каким другим определением (эффективно создавая пространство имен), но при этом они обращаются к одному и тому же бину.