Spring IoC Container With XML
Want to learn more about the Spring IoC container and how to implement it with an XML file? Check out this post where we look closer at Spring IoC containers.
Join the DZone community and get the full member experience.
Join For FreeWhat Is the IoC Container?
The org.springframework.context.ApplicationContext
interface represents the Spring IoC container. This container instantiates, configures, and assemble beans by using externally provided configuration metadata.
ApplicationContext
and BeanFactory
are the same, but the ApplicationContext
adds more enterprise-related functionality. In short, the ApplicationContext
is a superset of the BeanFactory
.
"Control of the managing bean and it's lifecycle" is part of the container and not the programmers, which is why it is named the "Inversion of Control."
What Is Configuration Metadata?
Configuration metadata represents how you, as an application developer, tell the Spring Container to instantiate, configure, and assemble the objects in your application.
This configuration metadata is nothing but bean definitions. BeanDefinitions
are provided in the form of an XML file, annotations, or a Java config class.
Forms of metadata with the Spring container are: XML-based configuration, annotation-based configuration, and Java-based configuration.
The following image represents how IoC containers work with the configuration metadata.
Before having deep dive into the configuration, we will understand a couple of conceptsat a very high level.
DI (Dependency Injection)
DI is a design pattern and is the act of connecting objects with other objects, or "injecting" objects into other objects. Dependency injections are performed by an assembler rather than by the objects themselves.
Having DI is the opposite of having a hardcore dependency.
There are two types of DI: the Constructor Injection and Setter Injection.
Ways to Define a Bean in an XML-Based Configuration
Since the application developer provides the configuration of metadata to the IoC container in the form of an XML file, we can define one or more bean definition in this configuration file. In this configuration, bean is defined as the <bean/> element inside a top-level <beans/> element.
Configuration signatures of the bean definition (Constructor Injection):
<!-- Constructor-arg with 'ref' attribute -->
<bean id="..." class="...">
<constructor-arg ref="..."/>
</bean>
The <constructor-arg /> element defines the constructor argument and does so using a number of attributes, but 'ref' is the most common. It is used to tell the container that the value of this attribute is a reference to another bean.
<!-- Constructor-arg with 'value' attribute -->
<bean id="..." class="...">
<constructor-arg value="..."/>
</bean>
Another attribute that is commonly used is 'value.' This attribute is used when the value to inject is a scalar.
Examples
1. We can define a bean with no "id" and "name" attributes. The container generates a bean name by its own, as shown below.
//Bean Class
package com.kasegvikas.model;
public class ThingOne {
..
..
}
<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-3.0.xsd">
...
<bean class="com.kasegvikas.model.ThingOne" />
...
</beans>
In the above code, the generated name is com.kasegvikas.model.ThingOne#0.
2. Some different combinations of bean definitions with examples can be found here:
package com.kasegvikas.model;
public class ThingTwo {
private String name;
private int year;
public ThingTwo(String name, int year) {
this.name = name;
this.year = year;
}
@Override
public String toString() {
return "ThingTwo [name=" + name + ", year=" + year + "]";
}
}
// Clases ThingThree, ThingFour, ThingFive and ThingSix have same structure as like ThingTwo
beans.xml:
<beans>
<!-- Constructor argument with name and value attributes -->
<bean name="thingTwo" class="com.kasegvikas.model.ThingTwo">
<constructor-arg name="name" value="ThingTwo"/>
<constructor-arg name="year" value="2001"/>
</bean>
<!-- Constructor arguments with index -->
<bean name="thingThree" class="com.kasegvikas.model.ThingThree">
<constructor-arg index="0" value="ThingThree"/>
<constructor-arg index="1" value="2002"/>
</bean>
<!-- Constructor arguments with type matching -->
<bean name="thingFour" class="com.kasegvikas.model.ThingFour">
<constructor-arg type="String" value="ThingFour"/>
<constructor-arg type="int" value="2003"/>
</bean>
<!-- Constructor arguments with @ConstructorProperties -->
<bean name="thingFive" class="com.kasegvikas.model.ThingFive">
<constructor-arg name="nameProp" value="ThingFive"/>
<constructor-arg name="yearProp" value="2004"/>
</bean>
</beans>
Main class:
package com.kasegvikas.app;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.util.Assert;
import com.kasegvikas.model.ThingFive;
import com.kasegvikas.model.ThingFour;
import com.kasegvikas.model.ThingThree;
import com.kasegvikas.model.ThingTwo;
public class Application {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
ThingTwo thingTwo = (ThingTwo) context.getBean("thingTwo");
Assert.notNull(thingTwo, "This bean must not be null.");
System.out.println(thingTwo);
ThingThree thingThree = (ThingThree) context.getBean("thingThree");
Assert.notNull(thingThree, "This bean must not be null.");
System.out.println(thingThree);
ThingFour thingFour = (ThingFour) context.getBean("thingFour");
Assert.notNull(thingFour, "This bean must not be null.");
System.out.println(thingFour);
ThingFive thingFive = (ThingFive) context.getBean("thingFive");
Assert.notNull(thingFive, "This bean must not be null.");
System.out.println(thingFive);
}
}
Output:
ThingTwo [name=ThingTwo, year=2001]
ThingThree [name=ThingThree, year=2002]
ThingFour [name=ThingFour, year=2003]
ThingFive [name=ThingFive, year=2004]
The above examples are available on GitHub.
Conclusion
The Spring IoC container with DI and configuration metadata all work together to introduce the best way for de-coupled and fast application development. This makes the application developer's life easy and takes care of the bean's lifecycle.
Opinions expressed by DZone contributors are their own.
Comments