Области видимости request, session, application и websocket доступны, только если вы используете реализацию ApplicationContext в фреймворке Spring с поддержкой веб (например, XmlWebApplicationContext). Если вы используете эти области видимости с обычными IoC-контейнерами Spring, такими как ClassPathXmlApplicationContext, будет сгенерирован IllegalStateException c сообщением о неизвестной области видимости бина.

Начальная веб-конфигурация

Для поддержки создания области видимости бинов на уровне request, session, application и websocket (web-scoped бины) перед определением бина требуется провести небольшую начальную настройку. (Данная начальная настройка не требуется для стандартных областей видимости: singleton и prototype).

То, каким образом вы выполните эту начальную настройку, зависит от вашей конкретной среды сервлетов.

Если вы обращаетесь к бинам, находящимся в области видимости, в Spring Web MVC, то есть в рамках запроса, который обрабатывается Spring DispatcherServlet, никакой специальной настройки не требуется. DispatcherServlet уже раскрывает все соответствующие состояния.

Если вы используете веб-контейнер Servlet 2.5, в котором запросы обрабатываются вне Spring DispatcherServlet (например, при использовании JSF или Struts), вам необходимо зарегистрировать org.springframework.web.context.request.RequestContextListener ServletRequestListener. Для Servlet 3.0+ это можно сделать программно, используя интерфейс WebApplicationInitializer. В качестве альтернативы или для более старых версий контейнеров добавьте следующее объявление в файл web web.xml вашего веб-приложения:

<web-app>
    ...
    <listener>
        <listener-class>
            org.springframework.web.context.request.RequestContextListener
        </listener-class>
    </listener>
    ...
</web-app>

В качестве альтернативы, если есть проблемы с настройкой слушателя, рассмотрите возможность использования RequestContextFilter в Spring. Отображение фильтров зависит от окружающей конфигурации веб-приложения, поэтому вы должны изменить его соответствующим образом. В следующем листинге показана часть фильтра веб-приложения:

<web-app>
    ...
    <filter>
        <filter-name>requestContextFilter</filter-name>
        <filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>requestContextFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    ...
</web-app>

DispatcherServlet, RequestContextListener и RequestContextFilter делают одно и то же, а именно связывают объект HTTP-запроса с Thread, который обслуживает этот запрос. Это позволяет получить доступ к бинам, входящим в область видимости request или session, далее по цепочке вызовов.

Область видимости request

Рассмотрим следующую XML-конфигурацию для определения бина:

<bean id="loginAction" class="com.something.LoginAction" scope="request"/>

Контейнер Spring создает новый экземпляр бина LoginAction с помощью определения бина loginAction для каждого HTTP-запроса. То есть бин loginAction находится в области видимости на уровне HTTP-запроса. Можно сколько угодно изменять внутреннее состояние создаваемого экземпляра, поскольку другие экземпляры, созданные на основе того же определения бина loginAction, не видят этих изменений состояния. Они зависят от конкретного запроса. Если запрос завершает обработку, бин, находящийся в области видимости запроса, исключается.

При использовании компонентов, управляемых аннотациями, или конфигурации Java, аннотацию @RequestScope можно использовать для назначения компонента области видимости request. В следующем примере показано, как это сделать:

Java
@RequestScope
@Component
public class LoginAction {
    // ...
}
Kotlin
@RequestScope
@Component
class LoginAction {
    // ...
}

Область видимости в пределах сеанса

Рассмотрим следующую XML-конфигурацию для определения бина:

<bean id="userPreferences" class="com.something.UserPreferences" scope="session"/>

Контейнер Spring создает новый экземпляр бина UserPreferences с помощью определения бина userPreferences на время жизни одной HTTP Session. Иными словами, бин userPreferences эффективно располагается в области видимости на уровне HTTP Session. Как и в случае с бинами, находящимися в области видимости request, вы можете изменять внутреннее состояние созданного экземпляра сколько угодно, зная, что другие экземпляры HTTP Session, которые также используют экземпляры, созданные на основе того же определения бина userPreferences, не заметят этих изменений состояния, поскольку они относятся к отдельной HTTP Session. Если HTTP Session в конечном итоге исключается, бин, который привязан к этой конкретной HTTP Session, также исключается.

При использовании компонентов, управляемых аннотациями, или конфигурации Java можно использовать аннотацию @SessionScope, чтобы назначить компонент области видимости session.

Java
@SessionScope
@Component
public class UserPreferences {
    // ...
}
Kotlin
@SessionScope
@Component
class UserPreferences {
    // ...
}

Область видимости в пределах приложения

Рассмотрим следующую XML-конфигурацию для определения бина:

<bean id="appPreferences" class="com.something.AppPreferences" scope="application"/>

Контейнер Spring создает новый экземпляр бина AppPreferences, используя определение бина appPreferences единожды для всего веб-приложения. То есть бин appPreferences находится в области видимости на уровне ServletContext и хранится как обычный атрибут ServletContext. Он в некоторой степени похож на бин-одиночку Spring, но отличается от него двумя важными особенностями: Он является объектом-одиночкой для каждого ServletContext, а не для Spring ApplicationContext (которых может быть несколько в любом конкретном веб-приложении), и он фактически открывается, поэтому и виден как атрибут ServletContext.

При использовании компонентов, управляемых аннотациями, или конфигурации Java можно использовать аннотацию @ApplicationScope для назначения компонента области видимости application. В следующем примере показано, как это сделать:

Java
@ApplicationScope
@Component
public class AppPreferences {
    // ...
}
Kotlin
@ApplicationScope
@Component
class AppPreferences {
    // ...
}

Область видимости в пределах WebSocket

Область видимости WebSocket связана с жизненным циклом сессии WebSocket и применяется к приложениям STOMP over WebSocket.