Setter Based Dependency Injection in Spring

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“. As promised in the previous post, this post will help us understand the second form of dependency injections. Here I will introduce setter based dependency injection.

Setter Based Dependency Injection

There is another way of injecting dependencies into beans. After instantiating the bean, the container invokes the setter methods for the given property and sets the required property.

Let us inject our DataStore bean into OrderClient bean using a setter injection. As a part of this, we need to declare a setter for the DataStore bean in the OrderClient class and inject the property. Here is an example

It is perfectly normal to use a mix of both type of dependency injections. In an XML based configuration scenario,

  • it is wise to use constructor based dependency injection for properties which are mandatory and
  • setter based injection for properties which are optional and can be assigned reasonable default values within the class.

Choosing the right Dependency Injection

The answer to this question is my favorite. It depends on the scenario and needs. However, Spring team advocates constructor based DI over setter based DI for two good reasons.

  • If you don’t use setters, you make your beans immutable and you make sure that the required dependencies are not null.
  • Beans created with the help of constructor based dependency injection are always returned to the client in a fully initialized state.

However, sometimes a constructor injection based DI can cause un-resolvable circular dependencies.

For e.g. If there are two beans A and B such that the constructor of A requires an instance of B and the constructor of B requires an instance of A. It would throw a BeanCurrentlyInCreationException and prompt you of a possible circular dependency scenario. This would happen when we attempt to bootstrap the application as shown in this example:

XML Configuration for Sample Application

Code to Bootstrap the Sample Application

If you will run the above, it will certainly throw the error related to circular dependency.

A setter based injection can come handy here and you can successfully inject beans even if a circular dependency exists. Setter based injections can allow circular dependencies, but it is not a recommended practice.

If we can add setters in both the POJOs A and B and inject them with setter based injection, then there will be no circular dependencies. Here is the code for the same.

XML Configuration for Setter Injection

Code to Bootstrap the Sample Application

Avoiding Circular Dependency with Setter Based Dependency Injection

It seems to be the most logical behavior. In a constructor based injection the bean is returned after it has been fully instantiated.

When the container attempts to inject bean A into bean B, it starts instantiating bean B. But bean B requires bean A as its dependency, so it tries to fetch bean A but has already marked it under creation.

This means both the beans are under creation and none can be return until the other one is completely instantiated. Hence, the exception.

Whereas in setter based dependency injection, the container does not require to inject any bean during instantiation of the other bean. Hence, the constructor invoked is the default no argument constructor. It returns the bean after instantiating and the setters can be invoked later fulfilling the dependencies.

The setter based injections are also used in certain scenarios when you want to make your class open to reconfiguration, mostly in instrumentation scenarios or you want to manage them through JMX beans.

Also, many times its less of a choice if you are handling code from a third party library. You have to act appropriately based on what the library exposes.