Spring Framework Tutorial
Software Setup and Configuration (STS/Eclipse/IntelliJ)
Core Spring
Spring Annotations
Spring Data
Spring JDBC
Spring Security
In Spring, a bean's scope determines the lifecycle and visibility of that bean in the contexts it is deployed in. Out of the box, Spring provides several bean scopes like singleton
, prototype
, request
, session
, and application
. However, there are scenarios when you might want to define your own custom bean scope.
Here's a step-by-step guide to creating a custom bean scope in Spring:
Scope
InterfaceYou need to implement the org.springframework.beans.factory.config.Scope
interface. This interface has several methods that you have to provide implementations for:
get
: Return an instance (possibly shared or independent) of the object managed by this bean scope.remove
: Remove the object with the given name
from the underlying scope.registerDestructionCallback
: Register a callback to be executed upon destruction of the specified object in the scope.resolveContextualObject
: Resolve the contextual object for the given key, if any.getConversationId
: Return the conversation ID for the current underlying scope, if any.Once you have implemented the Scope
interface, you need to register the custom scope with the Spring container using the ConfigurableBeanFactory.registerScope()
method.
@Configuration public class CustomScopeConfig { @Autowired private ConfigurableBeanFactory beanFactory; @PostConstruct public void registerMyScope() { beanFactory.registerScope("myCustomScope", new MyCustomScope()); } }
Now that your custom scope is registered, you can use it just like the built-in scopes.
@Bean @Scope("myCustomScope") public MyBean myBean() { return new MyBean(); }
As an illustrative example, let's create a custom bean scope that scopes beans to the lifecycle of a single thread:
public class ThreadScope implements Scope { private final ThreadLocal<Map<String, Object>> threadScope = ThreadLocal.withInitial(HashMap::new); @Override public Object get(String name, ObjectFactory<?> objectFactory) { Map<String, Object> scope = threadScope.get(); if (!scope.containsKey(name)) { scope.put(name, objectFactory.getObject()); } return scope.get(name); } @Override public Object remove(String name) { return threadScope.get().remove(name); } @Override public void registerDestructionCallback(String name, Runnable callback) { // Custom cleanup can be done here if needed } @Override public Object resolveContextualObject(String key) { return null; } @Override public String getConversationId() { return String.valueOf(Thread.currentThread().getId()); } }
With this custom scope, beans are scoped to individual threads. If you fetch a bean from the context in a specific thread, you'll always get the same instance within that thread. However, in a different thread, you'll get a different instance.
Creating custom bean scopes can be a powerful way to control the lifecycle and visibility of beans in your application, but it's also a more advanced feature that can add complexity. It's essential to ensure that the custom scope fits well with your application's requirements and architecture.
Creating and Using Custom Scopes for Spring Beans:
Scope
interface and register them in the Spring application context.public class CustomScope implements Scope { // Implementation details }
Defining Custom Scope in Spring ApplicationContext:
<bean id="myBean" class="com.example.MyBean" scope="customScope"/>
Implementing a Custom Bean Scope in Spring:
public class CustomScope implements Scope { // Implementation details for create, destroy, and get }
How to Register and Configure Custom Scopes in Spring:
@Configuration public class AppConfig { @Bean public static CustomScope customScope() { return new CustomScope(); } }
Configuring Thread-Scoped Beans in Spring Framework:
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
Request-Scoped Beans and Custom Scopes in Spring MVC:
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)