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:

Java
Object get(String name, ObjectFactory<?> objectFactory)
Kotlin
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:

Java
Object remove(String name)
Kotlin
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:

Java
void registerDestructionCallback(String name, Runnable destructionCallback)
Kotlin
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:

Java
String getConversationId()
Kotlin
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:

Java
void registerScope(String scopeName, Scope scope);
Kotlin
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.

The following example uses 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.
Java
Scope threadScope = new SimpleThreadScope();
beanFactory.registerScope("thread", threadScope);
Kotlin
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>
When you put <aop:scoped-proxy/> in a <bean> declaration for implementation of FactoryBean, the scope is the factory bean itself, not the object returned from getObject().