Bean Life Cycle and Post Processors

Introduction

This is a series and it would make a lot of sense if read in a sequence. You can find all the posts under the heading “Spring Beginners to Professionals“. This is the eighth post of the series. The previous post introduced beans in Spring, this post will take the discussion further and talk about bean life cycle and post processors.

Bean Life Cycle

All the beans in a Spring application, follow a life cycle. A bean life cycle can be defined as the stages of a bean’s life. There are two phases in a typical bean life cycle. The initialization phase, and the destruction phase. Initialization is a multi step process. Below is the list of steps followed in initialization:

Steps for Initialization

  • To begin with, the container instantiates the bean using the BeanDefinition.
  • Upon instantiation, the container populates the properties of the bean.
  • After populating the properties of the bean, the container can optionally
    • Set the name for the bean
    • May set the class loader for the bean
    • Can also set the BeanFactory for the bean
  • The next step is to apply some post processing logic (if any) before the initialization is complete.
  • At this step the container, the container verifies the initialization and moves forward if
    • if all the properties of the bean are set and
    • there is no mis-configuration.
  • Next is execution of any custom code which you want to execute as a part of initialization of the bean.
  • And the last step is to apply some more post processing logic after the initialization is complete.

Similar to the initialization phase, there is a destruction phase which is triggered when the bean is to be destroyed. First it invokes the destroy method of the framework and then user supplied custom code (if any) is executed as a part of destruction.

We will refer to these steps in our discussions later in the series.

Bean Scope

A scope can be considered as a logical boundary within which a bean is deployed and known to the application. There are handful of scopes in Spring. Before moving on to the scopes defined by Spring, let us try to understand how a scope in general can be enforced.

Consider a scenario where I have a web application and I want a customer’s information to be available only to him/her during his session. In such a scenario, I have to define the scope of the customer object in such a way that it gets created with the login and gets destroyed with logout or may be inactivity for a pre-configured period.

Traditional Approach

In traditional applications, all this was done using pure Java code and everything was hand coded. A developer had to write the code carefully which will destroy the customer object after detecting a log out or inactivity.

There are many such scenarios, not just limited to the scope of the session of course. Consider another scenario where a Database Connection Pool has to be created. Now in a typical application, such a connection pool exists one per data source. This is typically implemented as a singleton pattern which guarantees only one connection pool object per data source.

Spring way of handling the scopes

Coming back to Spring’s bean scopes, the most important and widely used of them is the singleton scope. In fact this is the default scope for a Spring bean. By default a bean is created to be deployed in singleton scope if:

  • No scope information is provided or
  • No scope can be derived in a parent child hierarchy of beans

However, this singleton is not exactly similar to the objects created using the Singleton Design Pattern. The Singleton Design Pattern dictates hard coding the scope of the object so that only one instance of the particular class is created per class loader. Spring guarantees exactly one shared bean instance for the given bean definition per IoC container. Refer to the previous post to understand IoC container.

BeanPostProcessor

In the above section, we discussed about the bean life cycle which controls the initialization and destruction process of a bean. Mostly the Bean Life Cycle is well defined, but many a times application requirements need certain customization to it.

The customization can range from supplementing the current behavior to even replacing it completely. Java provides the concept of inheritance to make things extensible, but the kind of extension we are talking about are for the Spring’s application context and Spring provides a better way of doing it using the BeanPostProcessors.

For e.g.: If you want your beans to be aware of the factory by which they are created, then you can implement a post processor which can set the factory bean for each bean which is instantiated. Spring already does that using one of the post processor.

The point is, if you want any custom behavior after bean instantiation, you can actually write a custom post processor for that. Let us see how exactly can we do that.

It’s pretty simple, you need to implement the BeanPostProcessor interface and implement the two callback methods postProcessBeforeInitialization() and postProcessAfterInitialization() .

  • The postProcessBeforeInitialization method is invoked just before the initialization callback methods like afterPropertiesSet and custom init methods.
  • Alternatively the postProcessAfterInitialization method is called after the initialization callbacks.

If there are several bean post processors registered with the framework, the framework invokes their callbacks one by one, in the order of registration for the beans it instantiates.

BeanFactoryPostProcessor

This is almost similar to the BeanPostProcessor. However, it operates on the configuration metadata and is capable of potentially changing it before any other beans except BeanFactoryPostProcessor beans are instantiated by the container.

So a point worth noting is that, the very first beans which get instantiated by the container are the BeanFactoryPostProcessor beans. Post that the container instantiates the beans of type BeanPostProcessor. Then the regular beans get a chance to come to life.

Summary

This is the end of essential theoretical concepts around Spring beans. Now we can go into details of actually configuring and understanding the architectural aspect of the Spring Framework and instantiating beans. Remember, these are crucial questions in the interviews for Spring Framework. In case there is some doubt, please comment below and I would explain it with some examples.

Stay connected and keep learning.

  • Marcio Carvalho

    One important thing during beans initialization is that Spring detects now cycles. If you have a cyclic dependency you must refactor your classes. Probably, one of them has too many responsibilities.

    • Thanks for the comment! Really appreciate your input. I promise to incorporate this in the coming posts..

  • deepti mittal

    You talked about scope of beans and in case of singeton its one instance per IOC container. Can there be any use case where application will have 2 IOC containers?

    • That’s a very nice question Deepti. You see this behavior in enterprise applications where it is very common to use multiple application context. (mostly in a hierarchical fashion). Refer to my post http://techieme.in/understanding-the-beanfactory/ , which explains this with an example.

      • deepti mittal

        Thanks a lot for replying. Indeed that post explains about hierarchical application context very well.
        I have further question on making spring application thread safe.
        As I see most of the application have beans defined as singleton so what makes them thread safe.
        In case of controller classes probably you will not have any issues but in case of data models should those not be declared as Protoype as one of your post has given example of ID generator being protoype.

        • Really sorry for the delayed response! Somehow I missed the comment.

          The Spring application if written correctly will definitely be thread safe. You are right when you say that the data model beans should be declared as prototype as each instance would represent one record.

          That is how, the applications are written. I will discuss on this further when I write a post on Database connectivity in Spring.