Что такое scope Prototype для бинов в Spring?

«Что такое scope Prototype для бинов в Spring?» — вопрос из категории Spring, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Scope Prototype — это область видимости бина в Spring, при которой контейнер IoC создает новый экземпляр бина каждый раз, когда запрашивается его внедрение или выполняется getBean(). В отличие от singleton-бина (один экземпляр на контейнер), prototype обеспечивает независимое состояние для каждого использования.

Ключевые характеристики:

  • Жизненный цикл: Контейнер Spring отвечает только за создание и инициализацию (вызов @PostConstruct). Уничтожение (@PreDestroy) и очистка памяти ложится на клиентский код или вышестоящий scope (например, request).
  • Использование: Подходит для бинов с изменяемым состоянием, которые не должны разделяться между несколькими клиентами.

Способы определения:

  1. Аннотация @Scope:
    @Component
    @Scope("prototype")
    public class PrototypeService {
        private int counter = 0;
        public int getAndIncrement() {
            return counter++;
        }
    }
  2. В XML-конфигурации:
    <bean id="prototypeBean" class="com.example.PrototypeService" scope="prototype"/>

Пример и важное предупреждение:

@RestController
public class MyController {
    // ПЛОХО! Бин PrototypeService будет создан ОДИН РАЗ при создании синглтона MyController.
    @Autowired
    private PrototypeService badInjection; // Всегда один и тот же экземпляр!

    // ХОРОШО. Используем провайдер для получения нового экземпляра при каждом вызове.
    @Autowired
    private ObjectFactory<PrototypeService> prototypeServiceProvider;
    // Или: private Provider<PrototypeService> prototypeServiceProvider;

    @GetMapping("/test")
    public String test() {
        PrototypeService newInstance = prototypeServiceProvider.getObject();
        // Каждый вызов getObject() возвращает новый экземпляр PrototypeService
        return "Counter: " + newInstance.getAndIncrement(); // Всегда начнет с 0
    }
}

Когда использовать Prototype?

  • Когда бин содержит изменяемое состояние, специфичное для конкретного использования.
  • Когда создание бина недорого, а его состояние не должно переживать запрос.
  • В сочетании со scope request или session (которые сами являются специализированными prototype-ами).