Spring IoC контейнер: процесс разрешения зависимостей

Контейнер выполняет разрешение зависимостей бина следующим образом:

  • ApplicationContext создается и инициализируется с метаданными конфигурации, которые описывают все компоненты. Метаданные конфигурации могут быть указаны с помощью XML, кода Java или аннотаций.
  • Для каждого компонента его зависимости выражаются в форме свойств, аргументов конструктора или аргументов метода статичной фабрики (если вы используете его вместо обычного конструктора). Эти зависимости предоставляются компоненту, когда компонент фактически создается.
  • Каждый аргумент свойства или конструктора является фактическим определением значения, которое нужно установить, или ссылкой на другой компонент в контейнере.
  • Каждый аргумент свойства или конструктора, являющийся значением, преобразуется из указанного формата в фактический тип аргумента этого свойства или конструктора. По умолчанию Spring может преобразовать значение, предоставленное в строковом формате, во все встроенные типы, такие как int, long, String, boolean и т. д.

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

Круговые зависимости

Если вы используете преимущественно внедрение в конструкторе, можно создать неразрешимый сценарий циклической зависимости.

Например: класс A требует экземпляр класса B с помощью инжектора конструктора, а класс B требует экземпляр класса A с помощью инжектора конструктора. Если вы настраиваете bean-компоненты для классов A и B, которые будут внедряться друг в друга, контейнер IoC Spring обнаруживает эту циклическую ссылку во время выполнения и генерирует исключение BeanCurrentlyInCreationException.

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

В отличие от типичного случая (без циклических зависимостей), циклическая зависимость между bean-компонентом A и bean-компонентом B заставляет один из bean-компонентов быть введенным в другой до полной инициализации (классический сценарий типа "курица и яйцо").

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

Если не существует циклических зависимостей, когда один или несколько взаимодействующих bean-компонентов вводятся в зависимый bean-компонент, каждый сотрудничающий bean-компонент полностью настраивается перед вводом в зависимый bean-компонент. Это означает, что, если компонент A имеет зависимость от компонента B, контейнер Spring IoC полностью настраивает компонент B перед вызовом метода сеттера для компонента A. Другими словами, экземпляр компонента создается (если он не является предварительно созданным синглтоном), его зависимости установлены, и соответствующие методы жизненного цикла (такие как настроенный метод init или метод обратного вызова InitializingBean) вызываются.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки