Springs Dependency Injection

0

Inversion of control & Dependency Injection

In an application, we have multiple objects and each object has association with other objects.

It is important that we make sure that the object does what it is supposed to do in a loosely coupled way.

What does it mean?

Suppose Object A is dependent on B and C.

In order to test A, we should make sure that A’s success is not directly couple with B’s or C’s success. But if we can some how decouple A’s association on the concrete implementations of B and C, for example, abstracting out the implementation by their APIs using interfaces or abstract classes, then A, B and C can evolve independently.

One pending issue that still exists in the above example is where do we set the implementation of B’ and C’, in the most simplest case, it would be in the constructor of A.

public A() {
    b = new B();
    c = new C();
}

As you see, A is still dependent on the concrete implementations B and C. This dependency on implementation is inverted by allowing a container to create the objects (called beans in spring) where it figures out the dependencies and injects the implementations wherever we want.

What is wiring?

In the above example, A, B and C can be thought of as components. A’s functionality is dependent on B and C. This is very common in any application where a success of a component is dependent on other components. Therefore we can say that an application is composed of many components where the components are aware of each other and work together to achieve a piece of functionality. Spring as a container, helps us to create these associations and is called wiring.

How do we let the spring do the wiring?

We need to configure the beans either through XML file or annotation or through the code itself. We define in the XML how a bean looks like and the components it is dependent on.

BeanFactory

BeanFactory is spring’s container which parses the configurations files and creates a registry of beans. In the below test case, we create a BeanFactory and then a reader around the factory to load the definitions.

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
       default-lazy-init="false">
    <bean id="bar" class="springdemo.Bar"/>
</beans>

Below rest case uses BeanFactory as the container

    
public void testBeanFactory() throws Exception {
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    new XmlBeanDefinitionReader(factory).loadBeanDefinitions("springdemo/testBar.xml");
    assertTrue(factory.containsBean("bar"));
}

It takes care of the associations between collaborating objects as they are instantiated but this happens only when the bean is actually requested, that is, when getBean() is called.

 assertTrue(factory.getBean("bar") instanceOf springdemo.Bar);

 

ApplicationContext

ApplicationContext is the spring’s advanced container that provides additional support compared to BeanFactory and is the preferred way to configure the application. In the above example, in case of ApplicationContext, the singletons configured for eager instantiation are instantiated during the creation of context itself.

ApplicationContext vs BeanFactory

Additional things that ApplicationContext takes care of are:

  • Ability to resolve textual messages from a properties file
  • Publishing application events to interested event listeners

For more details read my article on ApplicationContext.

Eager instantiation of Singleton

The reader parses through the XML files, can be more than one, creates bean definition for each configured bean and caches in the factory container. If the bean is singleton and configured for eager instantiation, it will create the bean and cache it.

Bean Lifecycle

Below diagram shows the lifecycle of a bean from the instantiation to the point where it is read to be used. When the bean factory shutsdown, the contained beans also will be destroyed. If the bean has a destroy method, it will be called so that it clean up its resources if any.

In this article, I have introduced you to dependency injection and spring’s containers ApplicationContext and BeanFactory. If you want to about how the container parses the beans and loads them into its registry click here

Share.

Leave A Reply