Sunday, October 27, 2013

Custom Scope for Spring Bean

21/11/2012
One of the speciality of spring framework is the options it provide for customization. In the last article we saw about spring bean scopes available as part of standard implementation. In this article we shall see about custom scope that is available from Spring 2.0
Based on spring custom scope, we can define new scope as well as modify out of the box provided spring bean scopes. We will not be able to modify the standard singleton and prototype scopes but we can modify the request, session and global_session scopes. Though spring framework provides option to modify the existing scopes, its better not to touch it and also I don’t see any real use case that asks for overriding existing scopes.

Example scenarios where we can use spring bean custom scope are in,
  1. creating a bean scope where beans can be shared between servlet contexts
  2. creating a bean scope where beans can be shared within a same thread
  3. and a lot more spring custom scope example
  4. out of all these, I like the idea of having a custom scope for a Locale

1. Create the custom bean scope

org.springframework.beans.factory.config.Scope is an interface and by implementing it we create a custom scope in the spring container. This Scope interface contains four methods,
  • get(..) – this get method is to return the bean from the given scope
  • remove(..) – this method is to remove an object from the scope
  • registerDestructionCallback(..) – this method is a callback method and gets invoked when the object in this scope is destroyed
  • getConversationId() – This depends on the scope and implementation. For example session scope it returns the sessionid


Out of the above four get() is the mandatory operation and others are optional.
public class ThreadScope implements Scope {
private final ThreadLocal threadScope = new ThreadLocal() {
protected Object initialValue() {
return new HashMap();
}
};
 
public Object get(String name, ObjectFactory objectFactory) {
Map scope = (Map) threadScope.get();
Object object = scope.get(name);
if(object==null) {
object = objectFactory.getObject();
scope.put(name, object);
}
return object;
}
 
public Object remove(String name) {
Map scope = (Map) threadScope.get();
return scope.remove(name);
}
 
public void registerDestructionCallback(String name, Runnable callback) {
}
 
}

2. Register the created custom bean

Once we create the custom spring bean scope we need to register it with the spring container. There are two ways to do it. Either through programmatic registration or using conventional XML based configuration. For programmatic registration, we should get the bean factory and call the registerScope method as below,
Scope customScope = new ThreadScope();
beanFactory.registerScope("thread", customScope);
For XML based configuration to register,
<bean
class="org.springframework.beans.factory.config.CustomScopeConfigurer">
<property name="scopes">
<map>
<entry key="thread">
<bean class="com.javapapers.spring.ThreadScope"/>
</entry>
 
</map>
</property>
</bean>

3. Use the custom scope

<bean id="..." class="..." scope="thread"/>
You know something, Spring 3.0 comes with thread scope the class name is SimpleThreadScope.

No comments: