Область видимости singleton

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

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

Понятие бина-одиночки в Spring отличается от понятия шаблона-одиночки, определенного в книге о шаблонах "Банды четырёх" (Gang of Four/GoF). В случае объекта-одиночки GoF область видимости объекта жестко кодируется таким образом, что для каждого ClassLoader создается один и только один экземпляр конкретного класса. Область видимости одиночки в Spring лучше всего описать как per-container и per-bean. Это означает, что если вы определяете один бина для конкретного класса в одном контейнере Spring, контейнер Spring создает один и только один экземпляр класса, заданного этим определением бина. Область видимости singleton - это область видимости Spring по умолчанию. Чтобы определить бин как объект-одиночку в XML, вы можете определить бина способом, показанным в следующем примере:

<bean id="accountService" class="com.something.DefaultAccountService"/>
<!-- следующее эквивалентно, хотя и избыточно (по умолчанию используется область видимости singleton) -->
<bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>

Область видимости prototype

Не-singleton область видимости prototype для развертывания бина создает новый экземпляр бина каждый раз, когда выполняется запрос на этот конкретный бин. То есть бин внедряется в другой бин или запрашивается через вызов метода getBean() в контейнере. Как правило, следует использовать область видимости prototype для всех бинов, сохраняющих состояние, и область видимости singleton для бинов, не сохраняющих состояние.

Следующая схема иллюстрирует область видимости prototype в Spring:

(Объект доступа к данным (DAO) обычно не конфигурируется как прототип, потому что типичный DAO не сохраняет никакого диалогового состояния. Было проще повторно использовать ядро схемы для объекта-одиночки).

В следующем примере бин определяется как прототип в XML:

<bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>

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

В некотором смысле роль контейнера Spring в отношении бинов, входящих в область видимости prototype, является заменой оператора Java new. Все управление жизненным циклом после данного момента должно осуществляться с клиентской стороны. (Подробнее о жизненном цикле бина в контейнере Spring см. в разделе Обратные вызовы жизненного цикла).

Бины-одиночки с зависимостями прототип-бин

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

Однако, предположим, вам нужно, чтобы бин, находящийся в области видимости singleton, неоднократно получал новый экземпляр бина, находящегося в области видимости prototype, во время выполнения. У вас не получится внедрить зависимость от бина, находяшегося в области видимости prototype, в ваш бин-одиночку, потому что внедрение происходит только один раз, когда контейнер Spring создает экземпляр бина-одиночки, разрешает и внедряет его зависимости.