DI (Dependency Injection) is a programming design pattern, which is used to reduce coupling in an application. Dependency Injection allows the developers to inject (use) an object directly in a class, which means that they no longer need to depend on a class to create an object. Spring framework supports loose coupling between one module and other modules of an application by using Dependency Injection. The basic principle of DI is that objects define their dependencies (other objects they work with) using constructor argument or argument to a factory method. It means that objects should only have as many dependencies as are required to perform their job. In other words, we can say that the number of dependencies should be minimum in an application.
IoC (Inversion of Control) is a principle of software construction, where the developers no longer need to create objects from classes. Instead, an application gets the objects from outside sources such as an XML configuration file. The concept of Inversion of Control is used to reduce coupling in an application. Coupling is a term that describes the degree to which one module depends on another module for proper functioning of an application. Loose coupling allows easier maintainability and higher reusability of an application. In this way, IoC facilitates better software design. Spring IoC container is the core of the Spring framework. The two interfaces, such as ApplicationContext and BeanFactory, allow you to manage beans in the Spring IoC container.
The key benefit of injecting objects in an application is that you can modify the implementation part of dependencies without being concerned about the depending object. For example, if the Car class knows about its dependency on the Petrol class through an interface, any other effect of changes in the implementation of the Petrol class to the Car class is not required. Even if we modify the implementation of the Petrol class, it does not affect the Car class.
Let’s now discuss both these concepts in detail.
DI is a concept of injecting an object into a class rather than explicitly creating the object in a class since the IoC container inject an object into the class during runtime. The three important types of Dis are setter injection, constructor injection, and method injection Setter injection is implemented through Java Bean setter methods. The Constructor Injection is implemented through Constructor arguments, where the loC container is responsible for implementing methods at runtime. The method injection is implemented through a number of callback methods and an API for traditional lookup.
- Ensures that components are simpler to write and maintain, as they do not require runtime collaboration lookup
- Reduces coding effort, as JavaBeans can be injected in a class using Dependency Injection
- Allows business objects to run in different DI frameworks or outside any framework without any change in the code
Inversion of Control
The actual representation of the Spring IoC container is the BeanFactory interface. This interface is an implementation of the factory design pattern, which creates and destroys beans. Various implementations of the BeanFactory interface exist; the XmlBeanFactory class being the most commonly used BeanFactory implementation. This XmlBeanFactory class loads its beans based on the definitions specified in an XML file and takes this XML configuration metadata to create a fully configured system or application.
The two models of objects supported by the BeanFactory interface are as follows:
- Singleton: Serves as the default and most commonly used model in which the only shared Single Room serves as an instance of the object is retrieved on the lookup with a particular name. This object model is ideal for stateless service objects.
- Prototype: Refers to the non-singleton model. Every new retrieval of a bean results in the creation of a new object, and in this way, it is used to allow each caller to have its own distinct object references.
Two important methods in the BeanFactory interface are getBean(String name) and getBean(String name, Class requiredType) methods. The getBean(String name) method allows you to get a bean on the basis of the value of the name parameter. The getBean(String name, Class requiredType) method allows you to specify the required class of the returned bean and throws an exception if it doesn’t exist.
Sub-interfaces of BeanFactory provide extra functionality, such as message lookup, and configuring metadata of a bean. The following are the sub-interfaces of the BeanFactory interface:
- ListableBeanFactory: Provides methods to enumerate the beans in a bean factory. For example, the getBeanDefinitionNames() method of the Listable Bean Interface interface returns the names of all the beans defined in the factory, the getBeanNamesForType(Class type) method returns the names of all the bean classes of a certain type, and the getBeanDefinitionCount() method returns the number of bean classes defined in the factory.
- AutowireCapableBeanFactory: Helps in configuring an existing external object and facilitates its dependencies. This is done through the autowireBeanProperties and applyBeanPropertyValues() methods. By using the specified autowire strategy, the autowire) method creates a new bean instance of the given class.
- ConfigurableBeanFactory: Provides additional configuration options on a bean factory that can be applied during the bean initialization stage.
- ApplicationContext: Provides extra functionality of Bean Factory. This interface provides support for message lookup, internationalization, and an event handling mechanism.
AOP with Spring is one of the most striking features.