Java Spring - Bean Scope and Post processors
Now that we've covered Spring Dispatcher Servlet, we'll use this this tutorial to dive deep into Bean lifecycle and Bean post processors.
As already mentioned in our previous articles in this series, Spring framework is an open source Java platform that provides MVC infrastructure support for developing robust Java applications very easily and very rapidly using recommended MVC pattern.
Bean Scopes
In Spring, bean scope is used to decide which type of bean instance should be returned from the Spring container back to the caller.
There are five types of Bean scopes supported in Spring. Let’s look at each of them in detail.
Singleton
It returns a single bean instance per Spring IoC container. This single instance is stored in a cache of such singleton beans, and all subsequent requests and references for that named bean return the cached object. If no bean scope is specified in bean the configuration file, it defaults to singleton.
If you define one bean for a particular class in a single Spring container, then the Spring container will create one and only one instance of the class defined by that bean definition. The singleton scope is the default scope Spring.
To define a bean as a singleton in XML, we would write configuration like so:
<bean id="accountService" class="com.foo.DefaultAccountService"/>
<!-- the following is equivalent, though redundant (singleton scope is the default);-->
<bean id="accountService" class="com.foo.DefaultAccountService" scope="singleton"/>
<!-- the following is equivalent and preserved for backward compatibility in spring-beans.dtd -->
<bean id="accountService" class="com.foo.DefaultAccountService"
singleton="true"/>
Prototype
This returns a new bean instance each time when requested. It does not store any cached version like singleton.
To define a bean as a prototype in XML you would write the configuration like so:
<!-- using spring-beans-2.0.dtd -->
<bean id="accountService" class="com.foo.DefaultAccountService" scope="prototype"/>
<!-- the following is equivalent and preserved for backward compatibility in spring-beans.dtd -->
<bean id="accountService" class="com.foo.DefaultAccountService" singleton="false"/>
There is one quite important thing to be aware of when deploying a bean in the prototype scope, in that the lifecycle of the bean changes slightly. Spring does not manage the complete lifecycle of a prototype bean; the container instantiates, configures, decorates and otherwise assembles a prototype object, hands it to the client and then has no further knowledge of that prototype instance.
This means that while initialization lifecycle callback methods will be called on all objects regardless of scope, in the case of prototypes, any configured destruction lifecycle callbacks will not be called. It is the responsibility of the client code to clean up prototype scoped objects and release any expensive resources that the prototype bean(s) are holding onto.
Request
This returns a single bean instance per HTTP request. Consider the following bean definition:
<bean id="loginAction" class="com.foo.LoginAction" scope="request"/>
With the above bean definition in place, the Spring container will create a brand new instance of the LoginAction bean using the 'loginAction' bean definition for each and every HTTP request.
>>> When the request is finished processing, the bean that is scoped to the request will be discarded.
Session
This returns a single bean instance per HTTP session (user level session). Consider the following bean definition:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session"/>
With the above bean definition in place, the Spring container will create a brand new instance of the UserPreferences bean using the 'userPreferences' bean definition for the lifetime of a single HTTP Session.
>>> When the HTTP Session is eventually discarded, the bean that is scoped to that particular HTTP Session will also be discarded.
GlobalSession
This returns a single bean instance per global HTTP session. It is only valid in the context of a web-aware Spring ApplicationContext (Application level session).
Consider the following bean definition:
<bean id="userPreferences" class="com.foo.UserPreferences" scope="globalSession"/>
The global session scope is similar to the standard HTTP Session scope, and really only makes sense in the context of portlet-based web applications.
>>> It is worth noting that if we are writing a standard Servlet-based web application and we define one or more beans as having global session scope, the standard HTTP Session scope will be used, and no error will be raised.
Bean Post Processors
BPP beans are a special kind of bean that are created before any other beans and interact with newly created beans. With this construct, Spring gives you means to hook-up to and customize the lifecycle behavior simply by implementing a BeanPostProcessor yourself.
Having a custom BPP like
public class CustomBeanPostProcessor implements BeanPostProcessor {
public CustomBeanPostProcessor() {
System.out.println("0. Spring calls constructor");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean.getClass() + " " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(bean.getClass() + " " + beanName);
return bean;
}
}
would be called and print out the class and bean name for every bean that is created.
The BeanPostProcessor interface defines callback methods that you can implement to provide your own instantiation logic, dependency-resolution logic etc. You can also implement some custom logic after the Spring container finishes instantiating, configuring, and initializing a bean by plugging in one or more BeanPostProcessor implementations.
You can configure multiple BeanPostProcessor interfaces and you can control the order in which these BeanPostProcessor interfaces execute by setting the order property provided the BeanPostProcessor implements the Ordered interface.
The BeanPostProcessors operate on bean (or object) instances which means that the Spring IoC container instantiates a bean instance and then BeanPostProcessor interfaces do their work.
BeanPostProcessor class has two methods:
- postProcessBeforeInitialization - as the name makes clear, it is used to make sure required actions are taken before initialization. For example, we want to load certain property file/read data from the remote source/service.
- postProcessAfterInitialization - anything that we want to do after initialization before bean reference is given to the application.
Sequence of the questioned methods in the lifecycle:
- BeanPostProcessor.postProcessBeforeInitialization()
- init()
- BeanPostProcessor.postProcessAfterInitialization()
- destroy()
It gives us a chance to process an instance of a bean created by the IoC container after its instantiation and then again after the initialization lifecycle event has occurred on the instance. We could use this to process fields that were set, perform validation on a bean, or even look up values from a remote resource to set on the bean as defaults.
Conclusion
In this tutorial, we delved into Bean scopes and BeanPostProcessor beans which when used wisely can make your application light.
Continue to part 5 - Bean Inheritance and Dependency Injection.
Recent Stories
Top DiscoverSDK Experts
Compare Products
Select up to three two products to compare by clicking on the compare icon () of each product.
{{compareToolModel.Error}}
{{CommentsModel.TotalCount}} Comments
Your Comment