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 Personne
' private fields
Private _nom As String
Private _age As Integer
' default builder
Public Sub New()
End Sub
' properties associated with private fields
Public Property nom() As String
Get
Return _nom
End Get
Set(ByVal Value As String)
_nom = 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 chain
Public Overrides Function tostring() As String
Return String.Format("[{0},{1}]", nom, age)
End Function
' init method
Public Sub init()
Console.WriteLine("init personne {0}", Me.ToString)
End Sub
' close method
Public Sub close()
Console.WriteLine("destroy personne {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="personne1" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
destroy-method="close">
<property name="nom">
<value>Simon</value>
</property>
<property name="age">
<value>40</value>
</property>
</object>
<object id="personne2" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
destroy-method="close">
<property name="nom">
<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 test object
Private factory As XmlObjectFactory
<SetUp()> _
Public Sub init()
' create a factory instance
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 personne1 As Personne = CType(factory.GetObject("personne1"), Personne)
Console.WriteLine("personne1=" + personne1.ToString())
Dim personne2 As Personne = CType(factory.GetObject("personne2"), Personne)
Console.WriteLine("personne2=" + personne2.ToString())
personne2 = CType(factory.GetObject("personne2"), Personne)
Console.WriteLine("personne2=" + personne2.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
personne2 = CType(factory.GetObject("personne2"), Personne)
Console.WriteLine("personne2=" + personne2.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 Voiture
' private fields
Private _marque As String
Private _type As String
Private _propriétaire As Personne
' public property
Public Property marque() As String
Get
Return _marque
End Get
Set(ByVal Value As String)
_marque = 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 propriétaire() As Personne
Get
Return _propriétaire
End Get
Set(ByVal Value As Personne)
_propriétaire = Value
End Set
End Property
' default builder
Public Sub New()
End Sub
' three-parameter constructor
Public Sub New(ByVal marque As String, ByVal type As String, ByVal propriétaire As Personne)
' initialize private fields via their associated properties
With Me
.marque = marque
.type = type
.propriétaire = propriétaire
End With
End Sub
' car object identity string
Public Overrides Function tostring() As String
Return String.Format("[{0},{1},{2}]", marque, type, propriétaire.ToString)
End Function
' init-destroy methods
Public Sub init()
Console.WriteLine("init voiture {0}", Me.ToString)
End Sub
Public Sub destroy()
Console.WriteLine("destroy voiture {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="personne1" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
destroy-method="close">
<property name="nom">
<value>Simon</value>
</property>
<property name="age">
<value>40</value>
</property>
</object>
<object id="personne2" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
destroy-method="close">
<property name="nom">
<value>Brigitte</value>
</property>
<property name="age">
<value>20</value>
</property>
</object>
<!-- a car -->
<object id="voiture1" type="istia.st.springioc.demos.Voiture, 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="personne2"/>
</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="voiture1" type="istia.st.springioc.demos.Voiture, 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="personne2"/>
</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 singletons factory
Private factory As XmlObjectFactory
<SetUp()> _
Public Sub init()
' create a factory instance
factory = New XmlObjectFactory(New FileStream("spring-config-2.xml", FileMode.Open))
' log
Console.WriteLine("setup test")
End Sub
<TearDown()> _
Public Sub destroy()
' we destroy the singletons
factory.Dispose()
' we free the factory
factory = Nothing
' follow-up
Console.WriteLine("teardown test")
End Sub
<Test()> _
Public Sub demo2()
' singleton retrieval [car1]]
Dim voiture1 As Voiture = CType(factory.GetObject("voiture1"), Voiture)
Console.WriteLine("Voiture1=[{0}]", voiture1)
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 GroupePersonnes
' private fields
Private _membres() As Personne
Private _groupesDeTravail As Hashtable
' public property
Public Property membres() As Personne()
Get
Return _membres
End Get
Set(ByVal Value() As Personne)
_membres = Value
End Set
End Property
Public Property groupesDeTravail() As Hashtable
Get
Return _groupesDeTravail
End Get
Set(ByVal Value As Hashtable)
_groupesDeTravail = Value
End Set
End Property
' default builder
Public Sub New()
End Sub
' object identity string GroupeDePersonnes
Public Overrides Function tostring() As String
' browse the list of group members
Dim identité As String = "[membres=("
Dim i As Integer
For i = 0 To membres.Length - 2
identité += membres(i).ToString + ","
Next
identité += membres(i).ToString + "), groupes de travail=("
' browse the workgroup dictionary
Dim clés As IEnumerator = groupesDeTravail.Keys.GetEnumerator
Dim clé As Object
While clés.MoveNext
clé = clés.Current
identité += String.Format("[{0},{1}] ", clé, groupesDeTravail(clé))
End While
' we return the result
Return identité + "]"
End Function
' init-destroy methods
Public Sub init()
Console.WriteLine("init GroupeDePersonnes {0}", Me.ToString)
End Sub
Public Sub destroy()
Console.WriteLine("destroy GroupeDePersonnes {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="personne1" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
destroy-method="close">
<property name="nom">
<value>Simon</value>
</property>
<property name="age">
<value>40</value>
</property>
</object>
<object id="personne2" type="istia.st.springioc.demos.Personne, demo1" init-method="init"
destroy-method="close">
<property name="nom">
<value>Brigitte</value>
</property>
<property name="age">
<value>20</value>
</property>
</object>
<!-- a car -->
<object id="voiture1" type="istia.st.springioc.demos.Voiture, 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="personne2" />
</constructor-arg>
</object>
<!-- a group of people -->
<object id="groupe1" type="istia.st.springioc.demos.GroupePersonnes" init-method="init"
destroy-method="destroy">
<property name="membres">
<list>
<ref object="personne1" />
<ref object="personne2" />
</list>
</property>
<property name="groupesDeTravail">
<dictionary>
<entry key="Brigitte">
<value>Marketing</value>
</entry>
<entry key="Simon">
<value>Ressources humaines</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 test object
Private factory As XmlObjectFactory
<SetUp()> _
Public Sub init()
' create a factory instance
factory = New XmlObjectFactory(New FileStream("spring-config-3.xml", FileMode.Open))
' log
Console.WriteLine("setup test")
End Sub
<TearDown()> _
Public Sub destroy()
' we destroy the singletons
factory.Dispose()
' follow-up
Console.WriteLine("teardown test")
End Sub
<Test()> _
Public Sub demo3()
' retrieving the singleton [group1]
Dim groupe1 As GroupePersonnes = CType(factory.GetObject("groupe1"), GroupePersonnes)
Console.WriteLine("groupe1={0}", groupe1)
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