Может ли Singleton-бин в Spring иметь несколько экземпляров?

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

Ответ

По умолчанию — нет. Spring Container гарантирует, что для каждого контекста (ApplicationContext) существует только один экземпляр singleton-бина.

Однако, несколько экземпляров могут появиться в следующих случаях:

  1. Несколько ApplicationContext: Если одно и то же bean-определение объявлено в родительском и дочернем контекстах, каждый контекст будет управлять своим собственным экземпляром.
  2. Нарушение паттерна вручную: Если реализация класса бина не защищена от:
    • Многопоточности: Без синхронизации несколько потоков могут создать свои экземпляры.
    • Сериализации/Десериализации: После десериализации создается новый объект. Решение — реализовать метод readResolve().
    • Рефлексии: Приватный конструктор можно обойти с помощью Reflection API.

Пример проблемы с сериализацией и её решение:

public class MySingleton implements Serializable {
    private static final MySingleton INSTANCE = new MySingleton();
    private MySingleton() {}
    public static MySingleton getInstance() { return INSTANCE; }

    // Защита от создания нового экземпляра при десериализации
    protected Object readResolve() {
        return getInstance();
    }
}

В контексте Spring IoC такие проблемы обычно не возникают, так как жизненным циклом бина управляет контейнер.