Spring Dependency Injection Example with Constructor and Property Setter (XML)

A primary goal of Spring is to keep components as independent as possible, which allows these components to be reused , and also provides possibility to unit test them independently. Spring Dependency Injection principal fulfill this goal via injecting the dependency one component might need to complete its job, rather that component itself finding it’s dependency. In this post we will focus on XML based configuration.Check out Annotation example as well. Let’s get going.

Spring provides mainly two ways for dependency injection

  • Property Setter
  • Constructor Injection

1.Using Property Setter

In this approach, dependency is injected/provided using Setter Method. Property Setter approach is more widely used in industry and simple to understand.
a) Create Sample Bean

package com.websystique.spring;

import com.websystique.spring.domain.Encryption;

public class Communication {

	private Messaging messaging;
	 
	 /*
	 * DI via Setter
	 */
	public void setMessaging(Messaging messaging){
		this.messaging = messaging;
	}

	public void communicate(){
		messaging.sendMessage();
	}
}

b) Create Helper POJO interface and implementation

package com.websystique.spring.domain;

public interface Messaging {

	public void sendMessage();
}
package com.websystique.spring.domain.impl;

import com.websystique.spring.domain.Messaging;

public class ActiveMQMessaging implements Messaging{

	public void sendMessage() {
		System.out.println("Sending Message via Active MQ");
	}

}

c) Create Spring Configuration XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        					http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" />

	<bean id="communication" class="com.websystique.spring.Communication">
		<property name="messaging">
			<ref bean="activeMqMessaging" />
		</property>
	</bean>

</beans>

In above XML configuration, Spring will inject ‘activeMqMessaging’ bean into ‘communication’ bean using setter dependency injection. Communication’s setter method [setMessaging(Messaging messaing)] will be called to set the property.

d) create main and run application

package com.websystique.spring;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppMain {
	public static void main(String args[]){
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");
		Communication app = (Communication)context.getBean("communication");
		app.communicate();
	}
}

You will see following output :

Sending Message via Active MQ

2.Using Constructor Injection

In this approach, Spring injects the required dependency via Constructor argument[s].

a) Create Sample Bean

package com.websystique.spring;

import com.websystique.spring.domain.Encryption;

public class Communication {

	private Encryption encryption;
	
	/*
	 * DI via Constructor Injection
	 */
	public Communication(Encryption encryption){
		this.encryption = encryption;
	}


	public void communicate(){
		encryption.encryptData();
	}

}

b) Create Helper POJO interface and implementation

package com.websystique.spring.domain;

public interface Encryption {

	public void encryptData();
}
package com.websystique.spring.domain.impl;

import com.websystique.spring.domain.Encryption;

public class RSAEncryption implements Encryption{

	public void encryptData() {
		System.out.println("Encrypting data using RSA Encryption");
	}
}

c) Create Spring Configuration XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        					http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" />

	<bean id="communication" class="com.websystique.spring.Communication">
		<constructor-arg>
			<ref bean="rsaEncryption" />
		</constructor-arg>
	</bean>

</beans>

In above XML configuration, Spring will inject ‘rsaEncryption’ bean into ‘communication’ bean using constructor dependency injection. Communication’s one arg Constructor[ Constructor(Encryption encryption)] will be called.

Remark: Although constructor injection seems simple, it can easily lead to infamous constructor ambiguities in case you have multiple constructors with same number of arguments but different types and if implicit conversion is possible between different types. It happens mostly with primitive type (int, String etc..). You can get rid of these ambiguities using ‘type’ attribute of constructor-arg element to specify exact type of argument e.g.

	<bean id="communication" class="com.websystique.spring.Communication">
		<constructor-arg type="com.websystique.spring.domain.Encryption">
			<ref bean="rsaEncryption" />
		</constructor-arg>
	</bean>

d) create main and run application

package com.websystique.spring;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppMain {
	public static void main(String args[]){
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");
		Communication app = (Communication)context.getBean("communication");
		app.communicate();
	}
}

You will see following output :

Encrypting data using RSA Encryption

Using both approach together on same Bean

It is also possible to use them together in same bean, although on different items.

Bean Class

package com.websystique.spring;

import com.websystique.spring.domain.Encryption;
import com.websystique.spring.domain.Messaging;

public class Communication {

	private Messaging messaging;
	
	private Encryption encryption;
	
	/*
	 * DI via Constructor Injection
	 */
	public Communication(Encryption encryption){
		this.encryption = encryption;
	}

	/*
	 * DI via Setter
	 */
	public void setMessaging(Messaging messaging){
		this.messaging = messaging;
	}

	public void communicate(){
		encryption.encryptData();
		messaging.sendMessage();
	}

}

Spring Configuration Class

package com.websystique.spring.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Description;

import com.websystique.spring.Communication;
import com.websystique.spring.domain.Encryption;
import com.websystique.spring.domain.Messaging;
import com.websystique.spring.domain.impl.ActiveMQMessaging;
import com.websystique.spring.domain.impl.RSAEncryption;

@Configuration
public class AppConfig {

	@Bean(name = "communication")
	public Communication communication() {
		Communication communication = new Communication(encryption());
		communication.setMessaging(messaging());
		return communication;
	}

	@Bean(name = "encryption")
	@Description("This bean will be injected via setter injection")
	public Encryption encryption() {
		return new RSAEncryption();
	}

	@Bean(name = "messaging")
	@Description("This bean will be injected via setter injection")
	public Messaging messaging() {
		return new ActiveMQMessaging();
	}

}

Spring XML configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        					http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<bean id="activeMqMessaging" class="com.websystique.spring.domain.impl.ActiveMQMessaging" />

	<bean id="rsaEncryption" class="com.websystique.spring.domain.impl.RSAEncryption" />

	<bean id="communication" class="com.websystique.spring.Communication">
		<constructor-arg>
			<ref bean="rsaEncryption" />
		</constructor-arg>
		<property name="messaging">
			<ref bean="activeMqMessaging" />
		</property>
	</bean>

</beans>

In above configuration, we are using Property Setter approach to inject ‘activeMqMessaging’ bean into ‘messaging’ property. On the other hand, we are using Constructor Injection approach to inject ‘rsaEncryption’ bean into Communication constructor.

Run Main

package com.websystique.spring;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class AppMain {
	public static void main(String args[]){
		AbstractApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");

		Communication app = (Communication)context.getBean("communication");
	    app.communicate();
	}
}

You will see following output :

Encrypting data using RSA Encryption
Sending Message via Active MQ

That’s it.

Below is the Directory Structure for this post:

And referenced pom.xml for this project is:

<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>com.websystique.spring</groupId>
	<artifactId>SpringDIWithXMLExample</artifactId>
	<version>1.0.0</version>
	<packaging>jar</packaging>

	<name>SpringDIWithXMLExample</name>
	<properties>
		<springframework.version>4.0.6.RELEASE</springframework.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${springframework.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${springframework.version}</version>
		</dependency>
	</dependencies>
</project>

Download Source Code


References