Является ли бин со scope «prototype» в Spring потокобезопасным по умолчанию?

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

Ответ

Нет. Scope "prototype" означает, что Spring создаёт новый экземпляр бина при каждом запросе (через ApplicationContext.getBean() или инъекцию зависимости). Это изолирует экземпляры между собой, но не делает потокобезопасным сам класс бина.

Проблема: Если несколько потоков работают с одним и тем же экземпляром prototype-бина (например, он был сохранён в поле другого синглтон-бина), или если логика внутри класса не синхронизирована, состояние может быть повреждено.

Пример небезопасного prototype-бина:

@Component
@Scope("prototype")
public class PrototypeProcessor {
    private int localCounter = 0; // Состояние отдельного экземпляра

    public void process() {
        localCounter++; // Опасность, если этот метод вызывается из разных потоков для ОДНОГО экземпляра
        // ... логика обработки
    }
}

Когда prototype НЕ решает проблему потокобезопасности:

  • Если ссылка на созданный prototype-бин сохраняется в поле синглтона и используется разными потоками.
  • Если в классе бина используется статическое (static) изменяемое состояние, общее для всех экземпляров.

Рекомендации:

  • Проектировать prototype-бины как stateless (без изменяемых полей).
  • Для хранения состояния, специфичного для потока, использовать ThreadLocal.
  • Явно синхронизировать доступ к критическим секциям, если состояние необходимо.

Вывод: Scope определяет жизненный цикл и количество экземпляров, но не управляет конкурентным доступом к ним. Потокобезопасность — это ответственность реализации класса.