Show List

Spring Dependency Injection using XML Configuration

Spring Framework allows for flexible dependency injection (DI) using XML configuration. This approach separates dependency management from business logic, enabling loosely coupled and testable code. In this tutorial, you'll learn how to implement constructor and setter-based dependency injection using an XML file. We’ll build a simple Spring application with multiple components and wire them together through the springwiring.xml configuration file.

This example shows different steps used for Spring dependency Injection using XML Configuration file. XML configuration file is used to create and wire beans. Below is the structure of the project we are going to create for this example
1. Create Maven project (From Java IDE go to File => New => Project => Maven Project) and add spring-context dependency. pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.itcodescanner</groupId>
<artifactId>spring</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
</dependencies>
</project>
2. Create Harddisk interface, Sanddisk and WesternDigital classes implementing Harddisk in com.dependencies package. Harddisk interface has signature for methods read and write. These methods will be overridden in Sandisk and WesternDigital classes.
package com.dependencies;

public interface Harddisk {
public void read();
public void write();
}
package com.dependencies;

public class Sandisk implements Harddisk{
@Override
public void read() {
System.out.println("Reading from Sandisk");
}

@Override
public void write() {
System.out.println("Writing from Sandisk");
}
}
package com.dependencies;

public class WesternDigital implements Harddisk{
@Override
public void read() {
System.out.println("Reading from WD");
}

@Override
public void write() {
System.out.println("Writing from WD");
}
}
3. Create consumer classes Computer and Laptop in the com.devices package. These classes have dependency on Harddisk but we are not specifying which Harddisk they are going to use inside the classes.

The Computer class has constructor with Harddisk argument which is passed to the class when object is created. Laptop has a setter for Harddisk property.

There is switchOn method which calls read and write methods of the harddisk.
package com.devices;

import com.dependencies.Harddisk;

public class Computer {
private Harddisk harddisk;

public Computer(Harddisk harddisk) {
this.harddisk = harddisk;
}


public void switchOn(){
System.out.println("Computer is switched on");
harddisk.read();
harddisk.write();
}

}
package com.devices;

import com.dependencies.Harddisk;

public class Laptop {
private Harddisk harddisk;

public void setHarddisk(Harddisk harddisk) {
this.harddisk = harddisk;
}

public void switchOn(){
System.out.println("Laptop is switched on");
harddisk.read();
harddisk.write();
}
}
4. Create xml file springwiring.xml in the resources folder. This file is going to create Harddisk beans and and pass them to objects (beans) of Computer and Laptop. Constructor injection is used while creating computer bean and setter injection is used while creating laptop bean.

In the constructor injection we pass the dependency through constructor argument. In the setter inject dependency is provided though property of the class.
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

<bean id="harddiskA" class="com.dependencies.Sandisk" />
<bean id="harddiskB" class="com.dependencies.WesternDigital" />

<bean id="computer" class="com.devices.Computer">
<constructor-arg ref="harddiskA" />
</bean>

<bean id="laptop" class="com.devices.Laptop">
<property name="harddisk" ref="harddiskB" />
</bean>

</beans>
5. Create Workstation (main) class which will load the application context passing the xml to create and wire beans. Get the required bean from the application context and execute the method.

From the console output we can see that Sandisk was processed as dependency in the computer object and WD was processed as dependency in the laptop object.
import com.devices.Computer;
import com.devices.Laptop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Workstation {

public static void main(String[] args) {
ApplicationContext context
= new ClassPathXmlApplicationContext("springwiring.xml");

Computer computer = (Computer) context.getBean("computer");
computer.switchOn();

Laptop laptop = (Laptop) context.getBean("laptop");
laptop.switchOn();
}

}
Output:
Computer is switched on
Reading from Sandisk
Writing from Sandisk
Laptop is switched on
Reading from WD
Writing from WD

Process finished with exit code 0
Spring’s XML-based dependency injection provides a clear and decoupled way to wire your application components. By using constructor and setter injection through XML configuration, you gain fine-grained control over object creation and wiring. This technique is still relevant for legacy systems or scenarios where annotations or Java-based configurations are not ideal. Understanding XML configuration lays a solid foundation for mastering Spring’s full capabilities.

FAQ Section

1. What is the purpose of XML configuration in Spring?

XML configuration defines how Spring beans are created and wired together using tags and attributes in an external XML file.

2. What is the difference between constructor and setter injection?

Constructor injection provides dependencies at object creation time, while setter injection allows setting them after the object is created.

3. Can we mix constructor and setter injection in the same application?

Yes, Spring supports combining both types of injection for different beans as needed.

4. Is XML-based configuration still supported in modern Spring?

Yes. Although annotations and Java config are more popular, XML configuration is fully supported and useful in certain scenarios.

5. Where should I place the springwiring.xml file?

Place it in the src/main/resources directory so Spring can find it on the classpath.

6. What is ApplicationContext?

It is the Spring container that manages beans and supports features like dependency injection, lifecycle management, and event propagation.

7. Is XML-based DI better than annotation-based?

Neither is objectively better—it depends on the use case. XML is more declarative and externalized; annotations are more concise and modern.

 

    Leave a Comment


  • captcha text