Categories: spring

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

View Comments

  • Nice Article ! But the Java Config should use
    AnnotationConfigApplicationContext and instead of
    ClassPathXmlApplicationContext. It would be helpful for others if you could correct this.

  • "It happens mostly with primitive type (int, String etc..)..."

    String is not a primitive type ;) Still great job, hats off to you!

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

7 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

7 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

7 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

7 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago