The mechanism for determining the scope of beans is extensible. You can define your own scopes or even override
existing ones, although the latter is considered bad practice, and you cannot override the built-in
singleton
and prototype
scopes.
Creating a special scope
To integrate custom scopes into a Spring container, you must implement the org.springframework.beans.factory.config.Scope
interface, which is described in this section. To get an idea of how to implement custom scopes, check out the
Scope
implementations that come with the Spring Framework itself, as well as the javadoc Scope
, which provides more details the methods that need to be implemented
are described.
The Scope
interface has four methods for getting objects out of scope, removing them from scope, and
allowing them to be destroyed.
For example, the session scope implementation returns the copied bean that is included in the session scope (if it does not exist, the method returns a new instance of the bean, binding it to the session for further use). The following method returns an object from the underlying scope:
Object get(String name, ObjectFactory<?> objectFactory)
fun get(name: String, objectFactory: ObjectFactory<*>): Any
For example, implementing session-level scope removes a bean that is included in session-level scope from the
underlying session. An object must be returned, but null
may be returned if an object with the
specified name is not found. The following method removes an object from the underlying scope:
Object remove(String name)
fun remove(name: String): Any
The following method registers a callback that the scope should fire when it is destroyed or when the specified object in the scope is destroyed:
void registerDestructionCallback(String name, Runnable destructionCallback)
fun registerDestructionCallback(name: String, destructionCallback: Runnable)
For more information on destruction callbacks, see javadoc or in Spring's scope implementation.
The following method gets the dialog identifier for the underlying scope:
String getConversationId()
fun getConversationId(): String
This identifier is different for each scope. For a session-scoped implementation, this identifier could be the session identifier.
Using a special scope
After writing and testing one or more custom Scope
implementations, you need to make the Spring
container aware of your new scopes. The following method is the main method for registering a new Scope
in the Spring container:
void registerScope(String scopeName, Scope scope);
fun registerScope(scopeName: String, scope: Scope)
This method is declared in the ConfigurableBeanFactory
interface, which is accessible through the BeanFactory
property in most concrete ApplicationContext
implementations shipped with Spring.
The first argument of the registerScope(..)
method is a unique name associated with the scope. Examples
of such names in the Spring container itself are singleton
and prototype
. The second
argument to the registerScope(..)
method is the actual instance of the custom Scope
implementation that you want to register and use.
Assume that you wrote your own Scope
implementation and then registered it as shown in the following
example.
SimpleThreadScope
, which is included
with Spring but is not registered by default. The instructions will be the same for your own custom implementations
of Scope
.
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
val threadScope = SimpleThreadScope()
beanFactory.registerScope("thread", threadScope)
You can then create bean definitions that follow the scope rules of your custom Scope
implementation, as
shown below:
<bean id="..." class="..." scope="thread">
When using a custom Scope
implementation, you are not limited to programmatically registering the scope.
You can also register Scope
declaratively using the CustomScopeConfigurer
class, as shown
in the following example:
<?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/>
in a
<bean>
declaration for implementation of FactoryBean
, the scope is the factory bean
itself, not the object returned from getObject()
.
GO TO FULL VERSION