Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Spring: Spring, prototype bean, singleton, dependency injection, bean scope

Как добиться создания нового prototype bean внутри singleton?

Этот вопрос проверяет понимание жизненного цикла бинов в Spring и умение управлять областями видимости (scope) для решения проблемы внедрения зависимостей с разными скоупами.

Короткий ответ

В Spring singleton-бин, созданный один раз, не может напрямую внедрять prototype-бин, так как получит его единственный экземпляр. Чтобы получать новый prototype-бин при каждом вызове, можно использовать несколько подходов. Самый распространённый — внедрить не сам бин, а объект `ApplicationContext` и получать бин через `getBean()`. Другой способ — использовать аннотацию `@Lookup` на методе. Также можно реализовать интерфейс `ApplicationContextAware`. Эти методы позволяют singleton-у запрашивать свежий экземпляр prototype-бина при необходимости.

Длинный ответ

В Spring Framework область видимости (scope) бина определяет его жизненный цикл и количество создаваемых экземпляров. Singleton — это scope по умолчанию, при котором контейнер IoC создаёт ровно один экземпляр бина на всё приложение. Prototype scope, напротив, приводит к созданию нового экземпляра бина каждый раз, когда он запрашивается из контейнера или внедряется в качестве зависимости.

Проблема внедрения prototype в singleton

Если вы внедряете prototype-бин как зависимость в singleton-бин через @Autowired в поле или конструктор, Spring сделает это инъекцию только один раз — во время инициализации singleton-а. В результате singleton получит ссылку на один конкретный экземпляр prototype-бина и будет использовать его постоянно, что противоречит цели scope prototype.

Способы решения

Для получения нового экземпляра prototype-бина внутри singleton-бина при каждом обращении можно использовать следующие подходы:

  • Использование ApplicationContext: Внедрите ApplicationContext в singleton и вызывайте context.getBean(PrototypeBean.class) каждый раз, когда нужен новый экземпляр.
  • Аннотация @Lookup: Объявите абстрактный или конкретный метод в singleton-бине, аннотированный @Lookup. Spring подставит реализацию, которая будет возвращать новый prototype-бин.
  • Реализация ApplicationContextAware: Singleton может реализовать интерфейс ApplicationContextAware, чтобы получить доступ к контексту и затем запрашивать бины.
  • Использование ObjectFactory или Provider: Внедрите ObjectFactory<PrototypeBean> или javax.inject.Provider<PrototypeBean>. Их метод getObject() или get() будет возвращать новый экземпляр из контекста.

Пример кода с ObjectFactory

@Component
@Scope("singleton")
public class SingletonService {
    private final ObjectFactory<PrototypeBean> prototypeFactory;

    @Autowired
    public SingletonService(ObjectFactory<PrototypeBean> prototypeFactory) {
        this.prototypeFactory = prototypeFactory;
    }

    public void doWork() {
        PrototypeBean freshInstance = prototypeFactory.getObject();
        // Используем freshInstance
        System.out.println(freshInstance);
    }
}

@Component
@Scope("prototype")
public class PrototypeBean {
    private final UUID id = UUID.randomUUID();
    // ...
}

В этом примере каждый вызов doWork() приводит к получению нового экземпляра PrototypeBean с уникальным UUID.

Где применяется

Такая необходимость возникает, когда singleton-сервис должен выполнять операции, требующие изолированного состояния для каждой задачи. Например, обработка HTTP-запроса (где сам сервис — singleton, но для каждого запроса нужен отдельный объект-обработчик), создание временных объектов-строителей (builder) или объектов, хранящих контекст пользовательской сессии.

Вывод: Используйте ObjectFactory/Provider или @Lookup, когда singleton-компоненту необходимо каждый раз получать новый экземпляр prototype-зависимости. Это позволяет сохранить преимущества singleton (производительность, отсутствие состояния) и в то же время использовать свежие объекты с изолированным состоянием, когда это требуется по логике приложения.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • Spring

    Spring

Ключевые слова

#Spring

#prototype bean

#singleton

#dependency injection

#bean scope

Подпишись на Java Developer в телеграм