In a nutshell, the IoC container is responsible for instantiating/creating and configuring an object and assembling the dependencies between objects.
You might be wondering.. how does IoC container receive the data to do the above-mentioned? The answer is from 1 of 3 places: XML fle, Java code or Java annotations.
IoC Container is a framework in Spring that manages the life cycle of POJO’s (Plain Old Java Objects) and inserts them in the java program when required.
In general, there are 2 ways that Java objects declare their dependencies:
- by passing them as arguments to the constructor
- by passing them as arguments o a setter method of an object
There are two packages that are basis for the Spring’s IoC container: org.springframework.beans and org.springframework.context.
The BeanFactory interface manages many beans and in the same time, these beans have dependencies between themselves. It provides basic functionality and more importantly – it provides ApplicationContext which is a sub-interface of BeanFactory. It is read-only while the application is running and may be reloaded if the implementation allows it and it manages the life cycle of the beans.
At this point, dependencies are not managed by Java objects but are managed by the framework. There has been an inversion(if you know what I mean).
Configuration Metadata is the term given to the instructions that are related to the tasks I mentioned in the beginning of this tutorial – instantiation, configuration and assembly of the objects.
As you can see from the image above, what’s essentialy happening is the Configuration Metadata (instantiation, configuration and assembly of the objects) and the JOVOs are being passed to the IOC Container (most likely an instance of ApplicationContext).
How to instantiate an ApplicationContext
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml");
Think of the ApplicationContext also as simply configuration. It loads the “configuration” either from an XML file or annotations. The ApplicationContext needs to be created in the beginning of your application so it reads everything it needs for your application to read.
Just in case you are wondering, you can have many ApplicationContexts in your application. You can even make them read from the same configuration file. Is that a good practice? Depends on what you are trying to achieve. Most people would recommend having all your beans configured in a single place (via XML or another) and loaded by a single application context.
The following example is take from the original Spring documentation, feel free to check it out for in-depth insight about Spring.
services.xml
<?xml version="1.0" encoding="UTF-8"?> <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"> <!-- services --> <bean id="petStore" class="org.springframework.samples.jpetstore.services.PetStoreServiceImpl"> <property name="accountDao" ref="accountDao"/> <property name="itemDao" ref="itemDao"/> <!-- additional collaborators and configuration for this bean go here --> </bean> <!-- more bean definitions for services go here --> </beans>
Again, you can think of services.xml as a configuration file and the ApplicationContext loading/reading it.
Conclusion
Why would you want to use IoC Container when you could just get away with simple DI (Depedency Injection)?
Well here are a few reasons:
- Elegancy
- Ease of changing between production and test mode
- simply by changing the configuration
There is one downside however, and that is sometimes IoC container is a bit tricky to be implemented correctly.