5. Spring IoC in Practice
We will now use examples to put into practice what we have seen previously.
5.1. Example 1
The [Person.vb] class is as follows:
Namespace istia.st.springioc.demos
Public Class Person
' private fields
Private _name As String
Private _age As Integer
' default constructor
Public Sub New()
End Sub
' Properties associated with private fields
Public Property name() As String
Get
Return _name
End Get
Set(ByVal Value As String)
_name = Value
End Set
End Property
Public Property age() As Integer
Get
Return _age
End Get
Set(ByVal Value As Integer)
_age = Value
End Set
End Property
' identity string
Public Overrides Function tostring() As String
Return String.Format("[{0},{1}]", name, age)
End Function
' init method
Public Sub init()
Console.WriteLine("Initializing person {0}", Me.ToString)
End Sub
' close method
Public Sub close()
Console.WriteLine("destroy person {0}", Me.ToString)
End Sub
End Class
End Namespace
The class contains:
- two private fields, name and age, accessible via properties
- a toString method to retrieve the value of the [Person] object as a string
- an init method that will be called by Spring when the object is created, and a close method that will be called when the object is destroyed
To create objects of type [Person], we will use the following Spring [spring-config-1.xml] file:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
<object id="person1" type="istia.st.springioc.demos.Person, demo1" init-method="init"
destroy-method="close">
<property name="name">
<value>Simon</value>
</property>
<property name="age">
<value>40</value>
</property>
</object>
<object id="person2" type="istia.st.springioc.demos.Person, demo1" init-method="init"
destroy-method="close">
<property name="name">
<value>Brigitte</value>
</property>
<property name="age">
<value>20</value>
</property>
</object>
</objects>
This file
- defines two objects with respective keys "person1" and "person2" of type [Person]
- it initializes the properties [name, age] for each person
- It defines the methods to be called during the initial construction of the object [init-method] and during the destruction of the object [destroy-method]
For our tests, we will use NUnit test classes. The first will be as follows:
Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.springioc.demos
Namespace istia.st.springioc.tests
<TestFixture()> _
Public Class NunitTestSpringIocDemo1
' the object to be tested
Private factory As XmlObjectFactory
<SetUp()> _
Public Sub init()
' Create an instance of the factory
factory = New XmlObjectFactory(New FileStream("spring-config-1.xml", FileMode.Open))
' log
Console.WriteLine("setup test")
End Sub
<Test()> _
Public Sub demo()
' Retrieve [Person] objects from the Spring file using their keys
Dim person1 As Person = CType(factory.GetObject("person1"), Person)
Console.WriteLine("person1=" + person1.ToString())
Dim person2 As Person = CType(factory.GetObject("person2"), Person)
Console.WriteLine("person2=" + person2.ToString())
person2 = CType(factory.GetObject("person2"), Person)
Console.WriteLine("person2=" + person2.ToString())
End Sub
<TearDown()> _
Public Sub destroy()
' we destroy the singletons
factory.Dispose()
' release the factory resource
factory = Nothing
' follow-up
Console.WriteLine("teardown test")
End Sub
End Class
End Namespace
Comments:
- To retrieve the objects defined in the [spring-config-1.xml] file, we use an object of type [XmlObjectFactory]. There are other types of "factory" that allow access to the singletons in the configuration file. The [XmlObjectFactory] object is obtained in the [SetUp] attribute method of the test class and stored in a private variable. Note that the method with the <Setup()> attribute is executed before each test.
- The [spring-config-1.xml] file will be placed in the application’s [bin] folder
- Spring can use configuration files in various formats. The [XmlObjectFactory] object is used to parse a configuration file in XML format.
- Reading a Spring file returns an object of type [XmlObjectFactory], in this case the
factoryobject. Using this object, a singleton identified by the key**C**can be retrieved using**factory.getObject(C)**. - The [demo] method retrieves and displays the values of the singletons with keys "person1" and "person2".
The structure of the Visual Studio project is as follows:

Comments:
- The VS project is named [demo1]
- The [istia] folder contains the source code. The compiled code will go into the [bin] folder in the [demo1.dll] DLL:

- The [spring-config-1.xml] file is in the project's [bin] folder.
- The [bin] folder contains the files required by the application:
- Spring.Core.dll, Spring.Core.xml for Spring classes
- log4net.dll for Spring logs
- demo1.dll, which is the DLL generated by the project
The [demo1.dll] DLL generated by the project is loaded into the graphical testing tool [Nunit-Gui 2.2]. This tool automatically displays the Nunit classes present in the DLL:

Executing the [demo] method of the NUnit test yields the results shown above and listed below:
Comments:
- line 2: the test starts with the execution of the <Setup()> attribute method
- line 3: the operation
forced the creation of the bean [person1]. Because in the definition of the singleton [person1] we had written [init-method="init"], the [init] method of the created [Person] object was executed. The corresponding message is displayed.
- Line 4: The operation
displayed the value of the created [Person] object.
- Lines 5-6: The same thing happens for the key bean [person2].
- line 7: the last operation
person2 = CType(factory.GetObject("person2"), Person)
Console.WriteLine("person2=" + person2.ToString())
resulted in only one line of output:
It therefore did not cause the creation of a new object of type [Person]. If that had been the case, the [init] method would have been displayed, which is not the case here. This is the principle of the singleton. By default, Spring creates only a single instance of the beans in its configuration file. It is an object reference service. If asked for the reference to an object that has not yet been created, it creates it and returns a reference to it. If the object has already been created, Spring simply returns a reference to it.
- Lines 8–10: The attribute method <TearDown()> is executed (line 10). Inside it, the operation
causes the destruction of the singletons created by Spring. This causes each of them to execute their [close] method because we had written, in the configuration file, for each of them: "destroy-method=close". This is what the displays indicate:
Now that we have covered the basics of Spring configuration, we will be able to move a bit faster in our explanations.
5.2. Example 2
Consider the following new [Car] class:
Imports istia.st.springioc.demos
Namespace istia.st.springioc.demos
Public Class Car
' private fields
Private _brand As String
Private _type As String
Private _owner As Person
' public properties
Public Property brand() As String
Get
Return _brand
End Get
Set(ByVal Value As String)
_brand = Value
End Set
End Property
Public Property type() As String
Get
Return _type
End Get
Set(ByVal Value As String)
_type = Value
End Set
End Property
Public Property owner() As Person
Get
Return _owner
End Get
Set(ByVal Value As Person)
_owner = Value
End Set
End Property
' default constructor
Public Sub New()
End Sub
' Three-parameter constructor
Public Sub New(ByVal brand As String, ByVal type As String, ByVal owner As Person)
' Initialize the private fields via their associated properties
With Me
.brand = brand
.model = model
.owner = owner
End With
End Sub
' identity string of the Car object
Public Overrides Function tostring() As String
Return String.Format("[{0},{1},{2}]", make, model, owner.ToString)
End Function
' init-destroy methods
Public Sub init()
Console.WriteLine("init car {0}", Me.ToString)
End Sub
Public Sub destroy()
Console.WriteLine("destroy car {0}", Me.ToString)
End Sub
End Class
End Namespace
The class has:
- three private fields: _type, _make, and _owner. These fields can be initialized and read via public properties. They can also be initialized using the Car(String, String, Person) constructor. The class also has a no-argument constructor that allows you to first create an uninitialized [Car] object and then initialize it via its public properties.
- a toString method to retrieve the value of the [Car] object as a string
- an init method that will be called by Spring immediately after the object is created, a destroy method that will be called when the object is destroyed
To create objects of type [Car], we will use the following Spring [spring-config-2.xml] file:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
<!-- people -->
<object id="person1" type="istia.st.springioc.demos.Person, demo1" init-method="init"
destroy-method="close">
<property name="name">
<value>Simon</value>
</property>
<property name="age">
<value>40</value>
</property>
</object>
<object id="person2" type="istia.st.springioc.demos.Person, demo1" init-method="init"
destroy-method="close">
<property name="name">
<value>Brigitte</value>
</property>
<property name="age">
<value>20</value>
</property>
</object>
<!-- a car -->
<object id="car1" type="istia.st.springioc.demos.Car, demo1" init-method="init"
destroy-method="destroy">
<constructor-arg index="0">
<value>Peugeot</value>
</constructor-arg>
<constructor-arg index="1">
<value>307</value>
</constructor-arg>
<constructor-arg index="2">
<ref object="person2"/>
</constructor-arg>
</object>
</objects>
This file adds an object with the key "car1" of type [Car] to the previous definitions. To initialize this object, we could have written:
<object id="car1" type="istia.st.springioc.demos.Car, demo1" init-method="init"
destroy-method="destroy">
<constructor-arg index="0">
<value>Peugeot</value>
</constructor-arg>
<constructor-arg index="1">
<value>307</value>
</constructor-arg>
<constructor-arg index="2">
<ref object="person2"/>
</constructor-arg>
</object>
Instead of choosing the method already presented, we have chosen here to use the class’s Car(String, String, Person) constructor. Additionally, the singleton [car1] defines the method to be called during the object’s initial construction [init-method] and the method to be called during the object’s destruction [destroy-method].
For our tests, we will use the following NUnit test class [NunitTestSpringIocDemo2]:
Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.springioc.demos
Namespace istia.st.springioc.tests
<TestFixture()> _
Public Class NunitTestSpringIocDemo2
' the singleton factory
Private factory As XmlObjectFactory
<SetUp()> _
Public Sub init()
' Create an instance of the factory
factory = New XmlObjectFactory(New FileStream("spring-config-2.xml", FileMode.Open))
' log
Console.WriteLine("setup test")
End Sub
<TearDown()> _
Public Sub destroy()
' destroy the singletons
factory.Dispose()
' release the factory
factory = Nothing
' follow-up
Console.WriteLine("teardown test")
End Sub
<Test()> _
Public Sub demo2()
' Retrieve the singleton [car1]
Dim car1 As Car = CType(factory.GetObject("car1"), Car)
Console.WriteLine("Car1=[{0}]", car1)
End Sub
End Class
End Namespace
Comments:
- The <Setup()> and <TearDown()> attribute methods remain unchanged.
- The [demo2] method retrieves a reference to the [car1] singleton and displays it.
The Visual Studio project structure remains the same as before. Only two new classes have been added, along with a Spring configuration file:

Running the NUnit test yields the following results:

Let’s comment on the screen outputs:
Comments:
- line 2: attribute method [Setup] executed before each test, here [demo]
- line 3: Spring begins creating the singleton [car1]. This singleton has a dependency on the singleton [person2], which does not yet exist. The latter is therefore created and its [init] method executed.
- line 4: the singleton [car1] can now be created. Its [init] method is then executed.
- Line 5: The [demo2] method displays the value of the singleton [car1]
- Lines 6–8: The test’s [TearDown] method is executed. The singletons are destroyed, triggering the execution of their [destroy] methods
5.3. Example 3
We introduce the following new class [PersonGroup]:
Imports istia.st.springioc.demos
Namespace istia.st.springioc.demos
Public Class PeopleGroup
' private fields
Private _members() As Person
Private _workGroups As Hashtable
' public properties
Public Property members() As Person()
Get
Return _members
End Get
Set(ByVal Value() As Person)
_members = Value
End Set
End Property
Public Property workGroups() As Hashtable
Get
Return _workGroups
End Get
Set(ByVal Value As Hashtable)
_workgroups = Value
End Set
End Property
' default constructor
Public Sub New()
End Sub
' identity string of the PeopleGroup object
Public Overrides Function tostring() As String
' iterate through the list of group members
Dim identity As String = "[members=("
Dim i As Integer
For i = 0 To members.Length - 2
identity += members(i).ToString + ","
Next
identity += members(i).ToString + "), workgroups=("
' iterate through the workgroups dictionary
Dim keys As IEnumerator = workingGroups.Keys.GetEnumerator
Dim key As Object
While keys.MoveNext
key = keys.Current
identity += String.Format("[{0},{1}] ", key, workgroups(key))
End While
' return the result
Return identity + "]"
End Function
' init-destroy methods
Public Sub init()
Console.WriteLine("init PeopleGroup {0}", Me.ToString)
End Sub
Public Sub destroy()
Console.WriteLine("destroy PeopleGroup {0}", Me.ToString)
End Sub
End Class
End Namespace
Its two private members are:
_members: an array of people who are members of the group
_workGroups: a dictionary mapping a person to a work group
These private members are made accessible via public properties. The goal here is to demonstrate how Spring allows you to initialize complex objects, such as those with array or dictionary fields.
The Spring configuration file [spring-config-3.xml] will be as follows:
<?xml version="1.0" encoding="iso-8859-1" ?>
<!DOCTYPE objects PUBLIC "-//SPRING//DTD OBJECT//EN"
"http://www.springframework.net/dtd/spring-objects.dtd">
<objects>
<!-- people -->
<object id="person1" type="istia.st.springioc.demos.Person, demo1" init-method="init"
destroy-method="close">
<property name="name">
<value>Simon</value>
</property>
<property name="age">
<value>40</value>
</property>
</object>
<object id="person2" type="istia.st.springioc.demos.Person, demo1" init-method="init"
destroy-method="close">
<property name="name">
<value>Brigitte</value>
</property>
<property name="age">
<value>20</value>
</property>
</object>
<!-- a car -->
<object id="car1" type="istia.st.springioc.demos.Car, demo1" init-method="init"
destroy-method="destroy">
<constructor-arg index="0">
<value>Peugeot</value>
</constructor-arg>
<constructor-arg index="1">
<value>307</value>
</constructor-arg>
<constructor-arg index="2">
<ref object="person2" />
</constructor-arg>
</object>
<!-- a group of people -->
<object id="group1" type="istia.st.springioc.demos.PeopleGroup" init-method="init"
destroy-method="destroy">
<property name="members">
<list>
<ref object="person1" />
<ref object="person2" />
</list>
</property>
<property name="workgroups">
<dictionary>
<entry key="Brigitte">
<value>Marketing</value>
</entry>
<entry key="Simon">
<value>Human Resources</value>
</entry>
</dictionary>
</property>
</object>
</objects>
- The <list> tag allows you to initialize an array-type or IList-type field with different values.
- The <dictionary> tag allows you to do the same with a field that implements the IDictionary interface
For our tests, we will use the following NUnit test class [NunitTestSpringIocDemo3]:
Imports System
Imports Spring.Objects.Factory.Xml
Imports System.IO
Imports NUnit.Framework
Imports istia.st.springioc.demos
Namespace istia.st.springioc.tests
<TestFixture()> _
Public Class NunitTestSpringIocDemo3
' the object to be tested
Private factory As XmlObjectFactory
<SetUp()> _
Public Sub init()
' Create an instance of the factory
factory = New XmlObjectFactory(New FileStream("spring-config-3.xml", FileMode.Open))
' log
Console.WriteLine("setup test")
End Sub
<TearDown()> _
Public Sub destroy()
' destroy the singletons
factory.Dispose()
' followed by
Console.WriteLine("teardown test")
End Sub
<Test()> _
Public Sub demo3()
' Retrieve the singleton [group1]
Dim group1 As PeopleGroup = CType(factory.GetObject("group1"), PeopleGroup)
Console.WriteLine("group1={0}", group1)
End Sub
End Class
End Namespace
The [demo3] method retrieves the singleton [group1] and displays it.
The structure of the Visual Studio project remains the same as before, except that it now has two additional classes and a configuration file.

Executing the [demo3] method in the NUnit test yields the following results:

Comments:
- line 2: [Setup] attribute method executed before each test, here [demo]
- lines 3-4: Spring begins creating the singleton [group1]. This singleton depends on the singletons [person1, person2], which do not yet exist. These singletons are created and their [init] methods are executed.
- line 5: the singleton [group1] can now be created. Its [init] method is then executed.
- line 6: the [demo3] method displays the value of the singleton [group1]
- Lines 7–10: The test’s [TearDown] method is executed. The singletons are destroyed, triggering the execution of their [destroy] methods