2. Article 1 - Spring IoC
Objectives of this document:
- to explore the configuration and integration possibilities of the Spring framework (http://www.springframework.org)
- define and use the concept of IoC (Inversion of Control), also known as Dependency Injection
2.1. Configuring a 3-tier application with Spring
Consider a classic 3-tier application:
![]() |
We will assume that access to the business and DAO layers is controlled by Java interfaces:
- the [IArticlesDao] interface for the data access layer
- the [IArticlesManager] interface for the business layer
In the data access layer, or DAO (Data Access Object) layer, it is common to work with a DBMS and therefore with a JDBC driver. Consider the skeleton of a class accessing an articles table in a DBMS:
To perform an operation on the DBMS, every method requires a [Connection] object that represents the connection to the database, through which data will be exchanged between the database and the Java code. To create this object, four pieces of information are required:
the name of the DBMS JDBC driver class | |
the JDBC URL of the database to be used | |
the credentials used to establish the connection | |
The password for this username |
How can our previous [ArticlesDaoPlainJdbc] class obtain this information? There are several possibilities:
Solution 1 - the information is hard-coded in the class:
The drawback of this solution is that you have to modify the Java code whenever any of this information changes, such as when the password is changed.
Solution 2 - the information is passed to the object during its construction:
Here, the object receives the information it needs to function when it is constructed. The problem is then shifted to the code that passed it the four pieces of information. How did it obtain them? The following class [ArticlesManagerWithDataBase] in the business layer could construct an object [ArticlesDaoPlainJdbc] from the data access layer:
![]() |
We can see that, once again, the information needed to construct the [ArticlesDaoPlainJdbc] object is provided to the constructor of the [ArticlesManagerWithDataBase] object. We can imagine that this information is passed to it by a higher layer, such as the user interface layer. We thus gradually reach the highest layer of the application. Due to its position, this layer is not called by a layer that could pass it the configuration information it needs. We must therefore find an alternative to constructor-based configuration. The standard approach for configuring an application at its highest layer is to use a file containing all information likely to change over time. There may be multiple such files. Upon application startup, an initialization layer will then create all or part of the objects required by the application’s various layers.
There is a wide variety of configuration files. The current trend is to use XML files. This is the approach taken by Spring. The file configuring an [ArticlesDaoPlainJdbc] object might look like this:
An application is a set of objects that Spring calls beans, because they follow the JavaBean standard for naming accessors and initializers (getters/setters) of an object’s private fields. Objects in an application that serve a specific purpose are often created as a single instance. These are called singletons. Thus, in our multi-tier application example discussed here, access to the article database will be handled by a single instance of the [ArticlesDaoPlainJdbc] class. For a web application, these service objects serve multiple clients at once. A service object is not created for each client.
The Spring configuration file above allows for the creation of a single service object of type [ArticlesDaoPlainJdbc] in a package named [istia.st.articles.dao]. The four pieces of information required by the constructor of this object are defined within a <bean>...</bean> tag. There will be as many such <bean> tags as there are singletons to be created.
When will the objects defined in the Spring file be constructed? Application initialization can be handled by the application’s main method, if it has one. For a web application, this might be the [init] method of the main servlet. Every application has a method that is guaranteed to be the first to execute. It is generally within this method that the construction of singletons takes place.
Let’s take an example. Suppose we want to test the previous [ArticlesDaoPlainJdbc] class using a JUnit test. A JUnit test class has a [setUp] method that is executed before any other method. This is where we will create the [ArticlesDaoPlainJdbc] singleton.
If we follow the approach of passing configuration information via the constructor, we will have the following test class:
The calling class [TestArticlesPlainJdbc] must know the four pieces of information required to initialize the [ArticlesDaoPlainJdbc] singleton to be constructed.
If we follow the approach of passing configuration information via a configuration file, we could have the following test class using the Spring file described above.
Here, the calling class [TestSpringArticlesPlainJdbc] does not need to know the information required to initialize the singleton to be constructed. It simply needs to know:
- [springArticlesPlainJdbc.xml]: the name of the Spring configuration file described above
- [articlesDao]: the name of the singleton to be created
A modification to the configuration file, outside of these two entities, has no impact on the Java code. This method of configuring an application’s objects is very flexible. To configure itself, the application needs to know only two things:
- the name of the Spring file containing the definitions of the singletons to be created
- the names of these singletons, which the Java code uses to obtain a reference to the objects they have been associated with via the configuration file
2.2. Dependency Injection and Inversion of Control
Let’s now introduce the concept of Dependency Injection used by Spring to configure applications. The term Inversion of Control (IoC) is also used. Consider the construction of the [ArticlesManagerWithDataBase] singleton in the business layer of our application:
![]() |
To access data from the DBMS, the business layer must use the services of an object implementing the [IArticlesDao] interface, for example, an object of type [ArticlesDaoPlainJdbc]. The code for the [ArticlesManagerWithDataBase] class might look like the following:
public class ArticlesManagerWithDataBase implements IArticlesManager {
// a data access instance
private IArticlesDao articlesDao;
....
public ArticlesManagerWithDataBase (String driverClassName, String url, String user, String pwd, ...) {
...
// creation of the data access service
articlesDao = (IArticlesDao)new ArticlesDaoPlainJdbc(driverClassName, url, user, pwd);
...
}
public ... doSomething(...){
...
}
}
The [ArticlesDaoPlainJdbc] class is supposed to implement the [IArticlesDao] interface here:
To create the [IArticlesDao] singleton required for the class to function, its constructor explicitly uses the name of the class that implements the [IArticlesDao] interface:
We therefore have a hard-coded dependency on the class name in the code. If the class implementing the [IArticlesDao] interface were to change, the code in the previous constructor would need to be modified. We have the following relationships between the objects:
![]() |
The [ArticlesManagerWithDataBase] class itself takes the initiative to create the [ArticlesDaoPlainJdbc] object it needs. Returning to the term "inversion of control," we can say that it is the one that has the "control" to create the object it needs.
If we were to write a JUnit test class for the [ArticlesManagerWithDataBase] class, it might look something like this:
The test class creates an instance of the business class [ArticlesManagerWithDataBase], which in turn creates an instance of the data access class [ArticlesDaoPlainJdbc] in its constructor.
The Spring solution eliminates the need for the business class [ArticlesManagerWithDataBase] to know the name [ArticlesDaoPlainJdbc] of the data access class it requires. This allows the class to be changed without modifying the Java code of the business class. Spring enables the simultaneous creation of both singletons: one for the data access layer and one for the business layer. The Spring configuration file will define a new bean:
The new feature is the bean defining the singleton of the business class to be created:
<bean id="articlesManager" class="istia.st.articles.domain.ArticlesManagerWithDataBase">
<property name="articlesDao">
<ref bean="articlesDao"/>
</property>
</bean>
- The class implementing the [articlesManager] bean is defined: [ArticlesManagerWithDataBase]
- The [articlesDao] field of the bean is assigned a value via the <property name="articlesDao"> tag. This is the field defined in the [ArticlesManagerWithDataBase] class:
For the [articlesDao] field to be initialized by Spring and its <property> tag, the field must follow the JavaBean standard and there must be a [setArticlesDao] method to initialize the [articlesDao] field. Note that the method name is derived precisely from the field name. Similarly, there is often a [get...] method to retrieve the field’s value. Here, it is the [getArticlesDao] method. In this new version, the [ArticlesManagerWithDataBase] class no longer has a constructor. It no longer needs one.
- The value that Spring will assign to the [articlesDao] field is that of the [articlesDao] bean defined in its configuration file:
<bean id="articlesManager" class="istia.st.articles.domain.ArticlesManagerWithDataBase">
<property name="articlesDao">
<ref bean="articlesDao"/>
</property>
</bean>
<bean id="articlesDao" class="istia.st.articles.dao.ArticlesDaoPlainJdbc">
<constructor-arg index="0">
.............
</bean>
- When Spring constructs the [ArticlesManagerWithDataBase] singleton, it will also create the [ArticlesDaoPlainJdbc] singleton:
- Spring will establish a dependency graph of the beans and see that the [articlesManager] bean depends on the [articlesDao] bean
- it will construct the [articlesDao] bean, i.e., an object of type [ArticlesDaoPlainJdbc]
- then it will construct the [articlesManager] bean of type [ArticlesManagerWithDataBase]
Now let’s imagine a JUnit test for the [ArticlesManagerWithDataBase] class. It might look like the following:
Let’s follow the creation process of the two singletons defined in the Spring file named [springArticlesManagerWithDataBase.xml].
- The [setUp] method above requests a reference to the bean named [articlesManager]
- Spring consults its configuration file, finds the [articlesManager] bean. If it has already been created, it simply returns a reference to the object (singleton); otherwise, it creates it.
- Spring detects the dependency of the [articlesManager] bean on the [articlesDao] bean. It therefore creates the [articlesDao] singleton of type [ArticlesDaoPlainJdbc] if it has not already been created (as a singleton).
- It creates the [articlesManager] singleton of type [ArticlesManagerWithDataBase]
This mechanism could be diagrammed as follows:
![]() |
Let’s recall the skeleton of the [ArticlesManagerWithDataBase] class:
Once Spring has finished constructing the singletons, we have an object of type [ArticlesManagerWithDataBase] whose [articlesDao] field is initialized without it knowing how. We say that we have injected a dependency into the [ArticlesManagerWithDataBase] object. We also say that we have inverted control: it is no longer the [ArticlesManagerWithDataBase] object that takes the initiative to create the object implementing the [IArticlesDao] interface that it needs; rather, it is the top-level application (when it initializes) that takes care of creating all the objects it needs by managing their interdependencies.
The main benefit of configuring the [ArticlesManagerWithDataBase] singleton via a Spring file is that we can now change the implementation class corresponding to the [articlesDao] field of the [ArticlesManagerWithDataBase] class without modifying its code. All we need to do is change the class name in the definition of the [articlesDao] bean in the Spring file:
will become, for example:
The [ArticlesManagerWithDataBase] bean will work with this new data access class without even knowing it.
2.3. Spring IoC in Practice
2.3.1. Example 1
Consider the following class:
The class has:
- two private fields, name and age
- getter and setter methods for these two fields
- 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 file:
This file will be named config.xml.
- It defines two beans with the respective keys "person1" and "person2" of type [Person]
- It initializes the [name, age] fields 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 a single JUnit test class to which we will successively add methods. The first version of this class will be as follows:
Comments:
- To retrieve the beans defined in the [config.xml] file, we use an object of type [ListableBeanFactory]. There are other types of objects that allow access to beans. The [ListableBeanFactory] object is obtained in the [setUp] method of the test class and stored in a private variable. It will thus be available to all test methods.
- The [config.xml] file will be placed in the application’s [ClassPath], i.e., in one of the directories searched by the Java Virtual Machine when it looks for a class referenced by the application. The [ClassPathResource] object is used to search for a resource in an application’s [ClassPath], in this case the [config.xml] file.
- Spring can use configuration files in various formats. The [XmlBeanFactory] object is used to parse a configuration file in XML format.
- Processing a Spring file returns an object of type [ListableBeanFactory], here the object bf. With this object, a bean identified by the key C is obtained via bf.getBean(C).
- The [test1] method retrieves and displays the values of the beans with keys "person1" and "person2".
The structure of our application’s Eclipse project is as follows:

Comments:
- The [src] folder contains the source code. The compiled code will go into a [bin] folder not shown here.
- The [config.xml] file is located at the root of the [src] folder. The project build automatically copies it to the [bin] folder, which is part of the application’s [ClassPath]. This is where it is looked up by the [ClassPathResource] object.
- The [lib] folder contains three Java libraries required by the application:
- commons-logging.jar and spring-core.jar for the Spring classes
- junit.jar for the JUnit classes
- The [lib] folder is also part of the application's [ClassPath]
Executing the [test1] method of the JUnit test yields the following results:
Comments:
- Spring logs a number of events using the [commons-logging.jar] library. These logs help us better understand how Spring works.
- The [config.xml] file was loaded and then processed
- The operation*
forced the creation of the [person1] bean. We can see the Spring log regarding this. Because we had written [init-method="init"] in the definition of the [person1] bean, the [init] method of the created [Person] object was executed. The corresponding message is displayed.
- The operation
displayed the value of the created [Person] object.
- The same phenomenon occurs for the [person2] key bean.
- The last operation
did not result in 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. If the object has already been created, Spring simply returns a reference to it.
- Note that there is no trace of the [close] method of the [Person] object, even though we had written [destroy-method=close] in the bean definition. It is possible that this method is only executed when the memory occupied by the object is reclaimed by the garbage collector. By the time this happens, the application has already finished, and writing to the screen has no effect. To be verified.
Now that we have covered the basics of a Spring configuration, we will be able to move through our explanations a bit more quickly.
2.3.2. Example 2
Consider the following new [Car] class:
The class has:
- three private fields: type, make, and owner. These fields can be initialized and read using the public get and set methods. They can also be initialized using the Car(String, String, Person) constructor. The class also has a no-argument constructor to comply with the JavaBean standard.
- 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 close method that will be called when the object is destroyed
To create objects of type [Car], we will use the following Spring [config.xml] file:
This file adds a bean with the key "car1" of type [Car] to the previous definitions. To initialize this bean, we could have written:
Rather than choosing the method already presented, we have chosen here to use the class’s Car(String, String, Person) constructor. Additionally, the [car1] bean 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 JUnit test class already presented, adding the following [test2] method to it:
The [test2] method retrieves the [car1] bean and displays it.
The structure of the Eclipse project remains the same as in the previous test. Executing the [test2] method of the JUnit test yields the following results:
Comments:
- The [test2] method requests a reference to the [car1] bean
- Line 4: Spring begins creating the [car1] bean because this bean has not yet been created (singleton)
- line 6: because the bean [car1] references the bean [person2], the latter bean is in turn constructed
- line 7: the bean [person2] has been created. Its [init] method is then executed.
- Line 9: Spring indicates that it will use a constructor to create the bean [car1]
- line 10: the bean [car1] has been created. Its [init] method is then executed.
- line 11: the [test2] method displays the value of the [car1] bean
2.3.3. Example 3
We introduce the following new class [PersonGroup]:
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
Note here that the [PeopleGroup] class does not define a no-argument constructor to comply with the JavaBean standard. Recall that in the absence of any constructor, there is a "default" constructor, which is the no-argument constructor that does nothing.
The goal here is to demonstrate how Spring allows for the initialization of complex objects, such as those with array or dictionary fields. We add a new bean to the previous Spring [config.xml] file:
- The <list> tag allows you to initialize a field of type array or one that implements the List interface with different values.
- The <map> tag allows you to do the same thing with a field that implements the Map interface
For our tests, we will use the JUnit test class already presented, adding the following [test3] method to it:
The [test3] method retrieves the [groupe1] bean and displays it.
The structure of the Eclipse project remains the same as in the previous test. Executing the [test3] method of the JUnit test yields the following results:
Comments:
- The [test3] method requests a reference to the [group1] bean
- line 4: Spring begins creating this bean
- Because the [group1] bean references the [person1] and [person2] beans, these two beans are created (lines 6 and 9) and their init methods are executed (lines 7 and 10)
- Line 11: The [group1] bean has been created. Its [init] method is now executed.
- Line 12: Display requested by the [test3] method.
2.4. Spring for configuring three-tier web applications
2.4.1. General application architecture
We want to build a 3-tier application with the following structure:
![]() |
- The three layers will be made independent through the use of Java interfaces
- The integration of the three layers will be handled by Spring
- We will create separate packages for each of the three layers, which we will call Control, Domain, and Dao. An additional package will contain the test applications.
The application structure in Eclipse could be as follows:

2.4.2. The DAO data access layer
The DAO layer will implement the following interface:
package istia.st.demo.dao;
public interface IDao1 {
public int doSomethingInDaoLayer(int a, int b);
}
- Write two classes, Dao1Impl1 and Dao1Impl2, that implement the IDao1 interface. The Dao1Impl1.doSomethingInDaoLayer method will return a+b, and the Dao1Impl2.doSomethingInDaoLayer method will return a-b.
- Write a JUnit test class to test the two previous classes
2.4.3. The business layer
The business layer will implement the following interface:
package istia.st.demo.domain;
public interface IDomain1 {
public int doSomethingInDomainLayer(int a, int b);
}
- Write two classes, Domain1Impl1 and Domain1Impl2, that implement the IDomain1 interface. These classes will have a constructor that takes a parameter of type IDao1. The Domain1Impl1.doSomethingInDomainLayer method will increment a and b by one, then pass these two parameters to the doSomethingInDaoLayer method of the received IDao1 object. The Domain1Impl2.doSomethingInDomainLayer method, on the other hand, will decrement a and b by one before doing the same thing.
- Write a JUnit test class to test the two previous classes
2.4.4. The user interface layer
The user interface layer will implement the following interface:
package istia.st.demo.control;
public interface IControl1 {
public int doSomethingInControlLayer(int a, int b);
}
- Write two classes, Control1Impl1 and Control1Impl2, that implement the IControl1 interface. These classes will have a constructor that takes a parameter of type IDomain1. The Control1Impl1.doSomethingInControlLayer method will increment a and b by one, then pass these two parameters to the doSomethingInDomainLayer method of the received IDomain1 object. The Control1Impl2.doSomethingInControlLayer method, on the other hand, will decrement a and b by one before doing the same thing.
- Write a JUnit test class to test the two previous classes
2.4.5. Integration with Spring
- Write a Spring configuration file that will determine which classes each of the three previous layers should use
- Write a JUnit test class using different Spring configurations to highlight the flexibility of the application
- Write a standalone application (main method) that passes two parameters to the IControl1 interface and displays the result returned by the interface.
2.4.6. A solution
2.4.6.1. The Eclipse project

The archives in the [lib] folder have been added to the project's [ClassPath].
2.4.6.2. The [istia.st.demo.dao] package
The interface:
A first implementation class:
A second implementation class:
2.4.6.3. The [istia.st.demo.domain] package
The interface:
A first implementation class:
A second implementation class:
2.4.6.4. The package [istia.st.demo.control]
The interface
A first implementation class:
A second implementation class:
2.4.6.5. [Spring] Configuration Files
A first [springMainTest1.xml]:
A second [springMainTest2.xml]:
2.4.6.6. The test package [istia.st.demo.tests]
A [main] test:
Results displayed in the Eclipse console:
Another test using the second [Spring] configuration file:
Results displayed in the Eclipse console:
Finally, a JUnit test:
2.5. Conclusion
The Spring framework offers true flexibility in both application architecture and configuration. We used the IoC concept, one of Spring’s two pillars. The other pillar is AOP (Aspect-Oriented Programming), which we did not cover. It allows you to add “behavior” to a class method through configuration without modifying the method’s code. In simple terms, AOP allows you to filter calls to certain methods:
![]() |
- the filter can be executed before or after the target method M, or both.
- The method M is unaware of these filters. They are defined in the Spring configuration file.
- The code of method M is not modified. Filters are Java classes that must be implemented. Spring provides predefined filters, particularly for managing DBMS transactions.
- Filters are beans and, as such, are defined in the Spring configuration file as beans.
A common filter is the transaction filter. Consider a method M in the business layer that performs two inseparable operations on data (a unit of work). It calls two methods, M1 and M2, in the DAO layer to perform these two operations.
![]() |
Because it resides in the business layer, method M abstracts away the underlying data storage. For example, it does not need to assume that the data is stored in a DBMS or that it must enclose the calls to methods M1 and M2 within a DBMS transaction. It is up to the DAO layer to handle these details. One solution to the previous problem is to create a method in the DAO layer that would itself call methods M1 and M2, wrapping these calls within a DBMS transaction.
![]() |
The AOP filtering solution is more flexible. It allows you to define a filter that, before calling M, will start a transaction and, after the call, will perform a commit or rollback as appropriate.
![]() |
There are several advantages to this approach:
- once the filter is defined, it can be applied to multiple methods, for example, all those that require a transaction
- the filtered methods do not need to be rewritten
- since the filters to be used are defined via configuration, they can be changed
In addition to IoC and AOP concepts, Spring provides numerous support classes for three-tier applications:
- for JDBC, SQLMap (iBatis), Hibernate, and JDO (Java Data Object) in the DAO layer
- for the MVC model in the User Interface layer
For more information: http://www.springframework.org.









