← Назад к вопросам

Будет ли вызван метод, помеченный как Prototype с аннотацией PreDestroy?

2.2 Middle🔥 111 комментариев
#Spring Boot и Spring Data#Spring Framework

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

@PreDestroy для Prototype бинов

Ответ: Нет, метод с аннотацией @PreDestroy не будет вызван для бинов со скопом Prototype.

Это важное различие в жизненном цикле Spring бинов, которое часто упускают при разработке.

Почему это происходит?

Spring контейнер полностью управляет жизненным циклом Singleton бинов (скоп по умолчанию). Для них контейнер:

  1. Создаёт экземпляр при инициализации
  2. Вызывает @PostConstruct методы
  3. При завершении приложения вызывает @PreDestroy методы

Для Prototype бинов ситуация иная:

@Component
@Scope("prototype")
public class PrototypeBean {
    @PostConstruct
    public void init() {
        System.out.println("PostConstruct вызван");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("PreDestroy НЕ будет вызван!");
    }
}

Жизненный цикл Prototype

  1. Создание: Spring создаёт новый экземпляр при каждом запросе getBean()
  2. @PostConstruct: Вызывается один раз при создании
  3. Использование: Бин передаётся клиенту
  4. Ответственность передаётся: Spring больше не управляет этим объектом
  5. @PreDestroy: Не вызывается — это задача клиента

Сравнение скопов

// Singleton - управляется Spring полностью
@Component
public class SingletonBean {
    @PostConstruct // ✓ Вызовется
    public void init() { }

    @PreDestroy // ✓ Вызовется при shutdown
    public void destroy() { }
}

// Prototype - Spring только создаёт
@Component
@Scope("prototype")
public class PrototypeBean {
    @PostConstruct // ✓ Вызовется при создании
    public void init() { }

    @PreDestroy // ✗ Не вызовется!
    public void destroy() { }
}

Как реализовать очистку для Prototype?

Используй интерфейс BeanFactory с getBean() и сам управляй жизненным циклом:

@Component
public class PrototypeConsumer {
    @Autowired
    private BeanFactory beanFactory;

    public void useBean() {
        PrototypeBean bean = beanFactory.getBean(PrototypeBean.class);
        try {
            // работа с бином
        } finally {
            // Нужно вызвать destroy() самостоятельно
            bean.destroy();
        }
    }
}

Или используй DisposableBean интерфейс для более явного управления:

@Component
@Scope("prototype")
public class PrototypeBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("Явное очистка");
    }
}

Вывод

Для Prototype бинов Spring не гарантирует вызов @PreDestroy, так как контейнер передаёт ответственность управления жизненным циклом клиентскому коду. Разработчик должен сам позаботиться об очистке ресурсов.