Механизм определения области видимости бинов является расширяемым. Вы можете определить свои собственные области видимости или даже переопределить существующие, хотя последнее считается порочной практикой, а также вы не можете переопределить встроенные области видимости singleton
и prototype
.
Создание специальной области видимости
Чтобы интегрировать специальные области видимости в контейнер Spring, необходимо реализовать интерфейс org.springframework.beans.factory.config.Scope
, который описан в этом разделе. Чтобы получить представление о том, как реализовать специальные области видимости, ознакомьтесь с реализациями Scope
, поставляемыми с самим Spring Framework, а также с javadoc Scope
, в котором более подробно описаны методы, которые нужно реализовать.
Интерфейс Scope
имеет четыре метода для получения объектов из области видимости, удаления их из области видимости и разрешения их уничтожения.
Например, реализация области видимости session возвращает скопированный бин, входящий в область видимости session (если такового не существует, метод возвращает новый экземпляр бина, привязав его к сессии для дальнейшего использования). Следующий метод возвращает объект из базовой области видимости:
Object get(String name, ObjectFactory<?> objectFactory)
fun get(name: String, objectFactory: ObjectFactory<*>): Any
Например, реализация области видимости на уровне сессии удаляет бин, входящий в область видимости на уровне сессии, из базовой сессии. Объект должен быть возвращен, но может вернуться null
, если объект с указанным именем не будет найден. Следующий метод удаляет объект из базовой области видимости:
Object remove(String name)
fun remove(name: String): Any
Следующий метод регистрирует обратный вызов, который область видимости должна инициировать при своем уничтожении или при уничтожении указанного объекта в области видимости:
void registerDestructionCallback(String name, Runnable destructionCallback)
fun registerDestructionCallback(name: String, destructionCallback: Runnable)
Более подробную информацию об обратных вызовах уничтожения см. в javadoc или в реализации области видимости в Spring.
Следующий метод получает диалоговый идентификатор для базовой области видимости:
String getConversationId()
fun getConversationId(): String
Этот идентификатор отличается для каждой области видимости. Для реализации на уровне области видимости session этот идентификатор может быть идентификатором сессии.
Использование специальной области видимости
После написания и тестирования одной или нескольких специальных реализаций Scope
, нужно сделать так, чтобы контейнер Spring узнал о ваших новых областях видимости. Следующий метод является главным методом регистрации нового Scope
в контейнере Spring:
void registerScope(String scopeName, Scope scope);
fun registerScope(scopeName: String, scope: Scope)
Этот метод объявляется в интерфейсе ConfigurableBeanFactory
, который доступен через свойство BeanFactory
в большинстве конкретных реализаций ApplicationContext
, поставляемых в составе Spring.
Первым аргументом метода registerScope(..)
является уникальное имя, связанное с областью видимости. Примерами таких имен в самом контейнере Spring являются singleton
и prototype
. Вторым аргументом метода registerScope(..)
является реальный экземпляр специальной реализации Scope
, который вы хотите зарегистрировать и использовать.
Предположим, что вы написали свою собственную реализацию Scope
, а затем зарегистрировали ее, как показано в следующем примере.
SimpleThreadScope
, который входит в состав Spring, но не регистрируется по умолчанию. Инструкции будут такими же для ваших собственных специальных реализаций Scope
.Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
val threadScope = SimpleThreadScope()
beanFactory.registerScope("thread", threadScope)
Затем вы можете создать определения бинов, которые будут соответствовать правилам определения области видимости вашей пользовательской реализации Scope
, как показано ниже:
<bean id="..." class="..." scope="thread">
При использовании пользовательской реализации Scope
вы не ограничены программной регистрацией области видимости. Вы также можете произвести регистрацию Scope
декларативно, используя класс CustomScopeConfigurer
, как показано в следующем примере:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="org.springframework.context.support.SimpleThreadScope"/>
</entry>
</map>
</property>
</bean>
<bean id="thing2" class="x.y.Thing2" scope="thread">
<property name="name" value="Rick"/>
<aop:scoped-proxy/>
</bean>
<bean id="thing1" class="x.y.Thing1">
<property name="thing2" ref="thing2"/>
</bean>
</beans>
<aop:scoped-proxy/>
в объявление <bean>
для реализации FactoryBean
, в область видимости входит сам фабричный бин, а не объект, возвращаемый из getObject()
.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ