The Spring IoC container is at the core of the Spring Framework as it creates the objects, wires them together, configures them, and manages their complete life cycle from creation to destruction. The Spring container uses dependency injection (DI) to manage the beans/components that make up an application.
1. What is the Spring IoC Container?
The org.springframework.beans
and org.springframework.context
packages are the basis for Spring Framework’s IoC container. It contains the main classes and interfaces that are core components to access the IoC container features.
The following two interfaces are at the heart of the Spring container.
- BeanFactory – provides the configuration framework and basic functionality capable of managing any type of object.
- ApplicationContext – extends BeanFactory and adds more enterprise-specific functionality such as integration with Spring AOP, message resource handling, and event publication.
The ApplicationContext
interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans by reading configuration metadata. The configuration metadata is represented in XML (legacy), Java annotations, or Java code.
Although we can create manually the Spring container via the BeanFactory interface, it is recommended to let this setup be handled automatically. When it is done automatically, for example in a web application, Spring’s ApplicationContext will be bootstrapped by the web container during application startup via a Spring-provided ContextLoaderListener class declared in the web.xml descriptor file
2. Spring ApplicationContext
The ApplicationContext interface is an extension to BeanFactory and adds more enterprise-specific functionality such as resolving textual messages from a properties file and publishing application events to interested event listeners.
The ApplicationContext container includes all the functionality of the BeanFactory container, so it is generally recommended over the BeanFactory. The BeanFactory
can still be used for lightweight applications like mobile devices or applet-based applications where data volume and speed are significant.
Spring supports the bootstrapping of ApplicationContext by manual coding (instantiate it manually and load the appropriate configuration) or in a web container environment via ContextLoaderListener.
2.1. Types of ApplicationContext
The most commonly used ApplicationContext
implementations that use XML configuration sources are:
- FileSystemXmlApplicationContext – loads the definitions of the beans from an XML file.
- ClassPathXmlApplicationContext – loads the definitions of the beans from an XML file. Additionally, we can set CLASSPATH properly because this container can look bean configuration XML file in CLASSPATH.
- WebXmlApplicationContext – loads the XML file with definitions of all beans from within a web application.
In the case of Java configuration or annotation-based configuration classes, the following container types are used:
- AnnotationConfigApplicationContext – accepts component classes as input – in particular
@Configuration
-annotated classes. It also plain@Component
types and JSR-330 compliant classes usingjavax.inject
annotations. - AnnotationConfigWebApplicationContext – produces a WebApplicationContext accepting similar inputs as above. It is the equivalent of AnnotationConfigApplicationContext for a web environment.
2.2. Creating an ApplicationContext Instance
A sample code for creating the application context will look like this. Note that, in most application scenarios, explicit user code is not required to instantiate a Spring IoC container. It is handled by the framework itself during the component scanning at the application startup.
After creating the ApplicationContext, we can use getBean()
to retrieve instances of the beans. Ideally, we should not getBean() at all, rather use @Autowired annotation for bean autowiring.
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.printMessage();
In the case of Java configuration, we can make use of AnnotationConfigWebApplicationContext as follows:
ApplicationContext context = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);
HelloWorld obj = (HelloWorld) context.getBean("helloWorld");
obj.printMessage();
When we run the above code, a Spring application context is created that contains the beans configured by the ApplicationConfiguration class.
@Configuration
public class ApplicationConfiguration {
@Bean
public HelloWorld helloWorld() {
return new HelloWorld();
}
//.. other beans
}
Note that we have created the bean using the stereotype annotations as follows. Here @Component is a meta-annotation that marks a class as a bean declaration.
@Component
public class HelloWorld {
public void printMessage(String message) {
log.info(message);
//other code
}
}
Next, a reference to the helloWorld bean is obtained by calling the getBean() method. Now we can execute the HelloWorld#printMessage() method using its reference variable obj.
3. Spring BeanFactory
The BeanFactory is essentially an interface for an advanced factory capable of maintaining a registry of different beans and their dependencies. The BeanFactory
enables us to read bean definitions and access them using the bean factory.
3.1. Creating BeanFactory
When using just the BeanFactory
we can create one and read in some bean definitions in the XML format as follows:
InputStream is = new FileInputStream("beans.xml");
BeanFactory factory = new XmlBeanFactory(is);
//Get bean
HelloWorld obj = (HelloWorld) factory.getBean("helloWorld");
Other ways to create a bean factory are as below:
Resource resource = new FileSystemResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
ClassPathResource resource = new ClassPathResource("beans.xml");
BeanFactory factory = new XmlBeanFactory(resource);
Basically, that’s all there is. Using getBean(String)
, we can retrieve instances of the beans; the client-side view of the BeanFactory
is surprisingly simple.
3.2. BeanFactory Methods
The BeanFactory
interface has only six methods for client code to call:
boolean containsBean(String)
: returns true if theBeanFactory
contains a bean definition or bean instance that matches the given name.Object getBean(String)
: returns an instance of the bean registered under the given name. Depending on how the bean was configured by theBeanFactory
configuration, either a singleton and thus shared instance or a newly created bean will be returned. ABeansException
will be thrown when either the bean cannot be found (in which case it’ll be aNoSuchBeanDefinitionException
), or an exception occurred while instantiating and preparing the bean.Object getBean(String, Class)
: returns a bean, registered under the given name. The bean returned will be cast to the given Class. If the bean cannot be cast, corresponding exceptions will be thrown (BeanNotOfRequiredTypeException
). Furthermore, all rules of thegetBean(String)
method apply (see above)Class getType(String name)
: returns theClass
of the bean with the given name. If no bean corresponding to the given name could be found, aNoSuchBeanDefinitionException
will be thrownboolean isSingleton(String)
: determines whether or not the bean definition or bean instance registered under the given name is a singleton. If no bean corresponding to the given name could be found, aNoSuchBeanDefinitionException
will be thrownString[] getAliases(String)
: Return the aliases for the given bean name, if any were defined in the bean definition
4. Conclusion
In this Spring tutorial, we learned the basics of the Spring IoC container, how it has been implemented using ApplicationContext interface, how it can be created programmatically and access the beans if not using autowiring.
Drop me your questions in the comments section.
Happy Learning !!
Comments