Что такое Scope (область видимости) бина в Spring?

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

Ответ

Scope (область видимости) в Spring определяет жизненный цикл и контекст существования экземпляра бина (объекта, управляемого контейнером IoC).

Основные области видимости (Scopes):

Scope Описание Контекст
singleton (по умолчанию) Контейнер создаёт один единственный экземпляр бина на всё приложение. Все запросы к этому бину получают один и тот же объект. ApplicationContext
prototype Контейнер создаёт новый экземпляр бина каждый раз, когда он запрашивается (через getBean() или инъекцию). Не управляется контейнером после создания и передачи.
request Создаётся новый экземпляр на каждый HTTP-запрос. Действует только в веб-контексте Spring. HTTP Request
session Создаётся один экземпляр на каждую HTTP-сессию пользователя. Действует только в веб-контексте. HTTP Session
application Создаётся один экземпляр на жизненный цикл ServletContext. Похож на singleton, но с привязкой к веб-контексту. ServletContext
websocket Создаётся один экземпляр на жизненный цикл WebSocket-сессии. WebSocket Session

Как задать Scope:

// Аннотацией @Scope
@Component
@Scope("prototype") // или @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class PrototypeBean {
    // Новый экземпляр при каждой инъекции
}

// В Java-конфигурации
@Configuration
public class AppConfig {
    @Bean
    @Scope("prototype")
    public MyService myService() {
        return new MyService();
    }
}

Важные нюансы:

  • singleton бины должны быть потокобезопасными (thread-safe), так как один экземпляр используется всеми потоками.
  • prototype бины: Контейнер Spring не управляет полным жизненным циклом prototype-бинов. Он создаёт экземпляр, настраивает его и передаёт клиенту. Методы уничтожения (@PreDestroy) не вызываются автоматически. Управление памятью ложится на клиентский код.
  • Внедрение зависимостей с разными Scope: Если singleton-бин зависит от prototype-бина, то prototype-бин будет внедрён только один раз при создании singleton-а. Чтобы получать новый prototype при каждом вызове, используйте lookup method injection или ObjectProvider.