Область видимості 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. Все управління життєвим циклом після цього моменту має здійснюватися з клієнтської сторони.

Біни-одинаки із залежностями прототип-бін

Якщо ти використовуєш біни, що знаходяться в області видимості singleton, із залежністю від бінів-прототипів, пам'ятай, що залежності дозволяються при створенні екземпляра. Таким чином, якщо впроваджувати залежність від біна-прототипу до біна, що знаходиться в області видимості singleton, створюється екземпляр нового біна-прототипу, а потім впроваджується до біна-одинака. Екземпляр прототипу — це єдиний екземпляр, який надається біну, що знаходиться в області видимості singleton.

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