Ответ
Нет, Spring не управляет полным жизненным циклом prototype-бина. Управление ограничивается фазами создания и настройки.
Жизненный цикл prototype-бина в Spring:
- Создание (Instantiation): Новый экземпляр создается при каждом запросе (через
ApplicationContext.getBean()или инъекцию зависимости). - Настройка (Population & Initialization): Spring внедряет зависимости и вызывает метод, помеченный аннотацией
@PostConstruct. - Уничтожение (Destruction): Spring НЕ вызывает метод
@PreDestroyдля prototype-бинов. Очистка ресурсов (закрытие соединений, файлов) и удаление из памяти — ответственность клиентского кода и JVM (сборщика мусора).
Почему так? Область prototype подразумевает, что Spring возвращает управление объектом клиенту сразу после его создания и настройки. Контейнер не отслеживает дальнейшую судьбу этих экземпляров.
Пример:
@Component
@Scope("prototype")
public class PrototypeService {
@PostConstruct
public void init() {
System.out.println("Prototype bean created and initialized.");
}
@PreDestroy
public void cleanup() {
// ЭТОТ МЕТОД НИКОГДА НЕ ВЫЗОВЕТСЯ SPRING'OM!
System.out.println("Это сообщение не появится.");
}
}
Для корректного освобождения ресурсов prototype-бинов необходимо использовать шаблоны вроде DisposableBean с явным вызовом метода уничтожения в клиентском коде.
Ответ 18+ 🔞
А, слушай, вот тут народ частенько путается, как с тем Герасимом из «Муму» — думает, раз Spring такой всемогущий, то он за всё отвечает, даже за прототипы. Ан хуй там плавал!
Вот смотри, чтобы не быть как тот немой крестьянин, который только «Му-му» мычит, давай разжую.
Spring для prototype-бина — это как мамка, которая родила, покормила, в школу первый раз отвела и говорит: «Всё, сынок, дальше сам, блядь!». Управление полным циклом? Да ни хуя подобного! Контейнер только две фазы делает:
- Создание (Instantiation): Каждый раз, когда ты просишь бина (через
getBean()или инъекцию), Spring, как заведённый, лепит новый экземпляр. Овердохуища копий может наделать. - Настройка (Population & Initialization): Впендюрит ему все зависимости, какие надо, и вызовет метод с
@PostConstruct. Типа, «на, сынок, портфель собран и бутерброд дал».
А дальше — всё, пипец, отвязка! Фаза уничтожения? Spring про неё для прототипов слышать не хочет. Метод @PreDestroy — это как та самая Муму для Герасима: он его в принципе видит, но вызвать — ни боже мой, не его собака, пусть клиентский код сам разбирается.
Почему так, ёпта? А потому что логика prototype — это «сделал и забыл». Контейнер выдал тебе объект, и с этого момента ты за него в ответе. Он не будет, как дурак, бегать за каждым экземпляром и следить, не пора ли его в утиль. Это ж пиздец какой overhead был бы!
Пример, чтобы вообще всё стало ясно:
@Component
@Scope("prototype")
public class PrototypeService {
@PostConstruct
public void init() {
System.out.println("Prototype bean создан и проинициализирован. Жизнь удалась!");
}
@PreDestroy
public void cleanup() {
// ЭТОТ МЕТОД НИКОГДА НЕ ВЫЗОВЕТСЯ SPRING'OM, ЯДРЁНА ВОШЬ!
// Это сообщение — несбыточная мечта, как мир во всём мире.
System.out.println("Это сообщение не появится. Вообще.");
}
}
Вот и получается, что если твой прототипный бин держит какие-то ресурсы (соединения, файлы), то Spring про них благополучно забьёт хуй. Закрывать их — это твоя головная боль, чувак. Придётся либо шаблоны проектирования использовать, либо вручную вызывать метод очистки. А то так и до утечек памяти недалеко, а потом сиди и думай: «И кто ж тут серит на крыше?».