Beans

Spring 3 Dependency Injection via Constructor and Setter

In this tutorial we are going to demonstrate the Spring Framework implementation of the Inversion of Control (IoC) principle, that is also known as Dependency Injection (DI). Dependency injection (DI) is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. DI exists in two major variants, Constructor-based dependency injection and Setter-based dependency injection.

Our preferred development environment is Eclipse. We are using Eclipse Juno (4.2) version, along with Maven Integration plugin version 3.1.0. You can download Eclipse from here and Maven Plugin for Eclipse from here. The installation of Maven plugin for Eclipse is out of the scope of this tutorial and will not be discussed. We are also using Spring version 3.2.3 and the JDK 7_u_21.

Let’s begin.

1. Create a new Maven project

Go to File -> Project ->Maven -> Maven Project.

New-Maven-Project

In the “Select project name and location” page of the wizard, make sure that “Create a simple project (skip archetype selection)” option is checked, hit “Next” to continue with default values.

Maven-Project-Name-Location

In the “Enter an artifact id” page of the wizard, you can define the name and main package of your project. We will set the “Group Id” variable to "com.javacodegeeks.snippets.enterprise" and the “Artifact Id” variable to "springexample". The aforementioned selections compose the main project package as "com.javacodegeeks.snippets.enterprise.springexample" and the project name as "springexample". Hit “Finish” to exit the wizard and to create your project.

Configure-Maven-Project

The Maven project structure is shown below:

Maven-project-structure

    It consists of the following folders:

  • /src/main/java folder, that contains source files for the dynamic content of the application,
  • /src/test/java folder contains all source files for unit tests,
  • /src/main/resources folder contains configurations files,
  • /target folder contains the compiled and packaged deliverables,
  • the pom.xml is the project object model (POM) file. The single file that contains all project related configuration.

2. Add Spring 3.2.3 dependency

  • Locate the “Properties” section at the “Overview” page of the POM editor and perform the following changes:
    Create a new property with name org.springframework.version and value 3.2.3.RELEASE.
  • Navigate to the “Dependencies” page of the POM editor and create the following dependencies (you should fill the “GroupId”, “Artifact Id” and “Version” fields of the “Dependency Details” section at that page):
    Group Id : org.springframework Artifact Id : spring-web Version : ${org.springframework.version}

Alternatively, you can add the Spring dependencies in Maven’s pom.xml file, by directly editing it at the “Pom.xml” page of the POM editor, as shown below:
 
pom.xml:

<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.javacodegeeks.snippets.enterprise</groupId>
	<artifactId>springexample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

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

	<properties>
		<spring.version>3.2.3.RELEASE</spring.version>
	</properties>
</project>

As you can see Maven manages library dependencies declaratively. A local repository is created (by default under {user_home}/.m2 folder) and all required libraries are downloaded and placed there from public repositories. Furthermore intra – library dependencies are automatically resolved and manipulated.

3. Constructor-based dependency injection

Constructor-based DI is accomplished by the container invoking a constructor with a number of arguments, each representing a dependency.

3.1 Create simple Spring beans

We create a simple Spring bean, HelloWorld and add a dependency to another bean, Foo. In this case, another bean is referenced in the bean, so the type is known, and matching can occur.
 
HelloWorld.java:

package com.javacodegeeks.snippets.enterprise.services;

public class HelloWorld {
	
/** Dependency on Foo class. */
	private Foo foo;

	/** a constructor so that the Spring container can 'inject' a Foo*/
	public HelloWorld(Foo foo){
		this.foo = foo;
	}
	public String toString(){
		return " HelloWorld! foo : \n " + foo;
	}
}

We also add three new dependencies to Foo bean of simple types and add two new constructors.
 
Foo.java:

package com.javacodegeeks.snippets.enterprise.services;

public class Foo {
	
	private String name;
	
	private String telephoneNumber;

	private int age;
	
	public Foo(String name, String telephoneNumber, int age){
		this.name = name;
		this.telephoneNumber = telephoneNumber;
		this.age = age;
	}
	
	public Foo(String name, int age, String telephoneNumber){
		this.name = name;
		this.age = age;
		this.telephoneNumber = telephoneNumber;
	}

	public String toString(){
		return " name : " + name+ " \n telephoneNumber : " + telephoneNumber + "\n age : " +age;
	}
}

3.2 Add xml configuration

The configuration xml file is set for the above beans as shown below:
 
applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
	<bean id="helloWorldBean"
		class="com.javacodegeeks.snippets.enterprise.services.HelloWorld">
		<constructor-arg ref="fooBean" />
	</bean>

	<bean id="fooBean" class="com.javacodegeeks.snippets.enterprise.services.Foo">
		<constructor-arg>
			<value>fooname</value>
		</constructor-arg>
		<constructor-arg>
			<value>100</value>
		</constructor-arg>
		<constructor-arg>
			<value>25</value>
		</constructor-arg>
	</bean>
</beans>

When a simple type is used in the bean, such as int, Spring cannot determine the type of the value, and so cannot match by type without help. For example, in fooBean definition, the values set for the first constructor might be used from the second one as well, since the value 100 can be converted either to String or to int. In order to avoid such type ambiguities, we must always specify the exact data type for constructor, via type attribute.
 
applicationContext.xml fooBean:

	<bean id="fooBean" class="com.javacodegeeks.snippets.enterprise.services.Foo">
		<constructor-arg type="java.lang.String">
			<value>fooname</value>
		</constructor-arg>
		<constructor-arg type="java.lang.String">
			<value>100</value>
		</constructor-arg>
		<constructor-arg type="int">
			<value>25</value>
		</constructor-arg>
	</bean>

3.3 Run the application

Through the ApplicationContext the beans are loaded to App.class.
 
App.java:

package com.javacodegeeks.snippets.enterprise;

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

import com.javacodegeeks.snippets.enterprise.services.HelloWorld;

public class App {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) {
	
			ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
			HelloWorld helloWorld = (HelloWorld) context.getBean("helloWorldBean");
			System.out.println(helloWorld);
	}
}

3.4 Output

When you execute the application you should see something like the output presented below:

 HelloWorld! foo : 
  name : fooname 
 telephoneNumber : 100
 age : 25

4. Setter-based dependency injection

Setter-based DI is accomplished by the container calling setter methods on the beans.

4.1 Create a simple Spring bean

We create a simple Spring bean, Bar and add a dependency to Foo. In this case, the Foo bean is injected via the setter method.
 
Bar.java:

package com.javacodegeeks.snippets.enterprise.services;

public class Bar {

	private Foo foo;
	
	public void setFoo(Foo foo){
		this.foo = foo;
	}
	
	public String toString(){
		return "Bar! Foo : \n" + foo;
	}
}

4.2 Add xml configuration

In applicationContext.xml the bean definition must be added.
 
applicationContext.xml barBean:

	<bean id="barBean" class="com.javacodegeeks.snippets.enterprise.services.Bar">
		<property name="foo">
			<ref bean="fooBean" />
		</property>
	</bean>

 
Another way to accomplish the Dependency Injection via the setter is using the @Autowired annotation. Thus, we can get rid of the <property> element in applicationContext.xml. The annotation is added to the setter of the injected bean. When Spring finds an @Autowired annotation used with setter methods, it tries to perform byType autowiring on the method.
 
Bar.class:

package com.javacodegeeks.snippets.enterprise.services;

import org.springframework.beans.factory.annotation.Autowired;

public class Bar {

	private Foo foo;
	
	@Autowired
	public void setFoo(Foo foo){
		this.foo = foo;
	}
	
	public String toString(){
		return "Bar! Foo : \n" + foo;
	}
}

In applicationContext.xml <context:annotation-config/> attribute is defined. It looks for annotations on beans in the same application context it is defined in.
 
applicationContext.xml:

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">
   
   <context:annotation-config/>
   
	<bean id="helloWorldBean"
		class="com.javacodegeeks.snippets.enterprise.services.HelloWorld">
		<constructor-arg ref="fooBean" />
	</bean>

	<bean id="fooBean" class="com.javacodegeeks.snippets.enterprise.services.Foo">
		<constructor-arg type="java.lang.String">
			<value>fooname</value>
		</constructor-arg>
		<constructor-arg type="java.lang.String">
			<value>100</value>
		</constructor-arg>
		<constructor-arg type="int">
			<value>25</value>
		</constructor-arg>
	</bean>
	<bean id="barBean" class="com.javacodegeeks.snippets.enterprise.services.Bar">		
	</bean>
</beans>

4.3 Run the application

App2.class:

package com.javacodegeeks.snippets.enterprise;

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

import com.javacodegeeks.snippets.enterprise.services.Bar;

public class App2 {

	@SuppressWarnings("resource")
	public static void main(String[] args) {
		
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Bar bar = (Bar) context.getBean("barBean");
		System.out.println(bar);
	}
}

4.4 Output

The output of the setter-based dependency injection example is the one below:
 

Bar! Foo : 
 name : fooname 
 telephoneNumber : 100
 age : 25

 
This was an example of how to use Dependency Injection via a Constructor and a Setter in Spring 3.2.3.
 
Download the Eclipse project of this part : SpringDIConstructorSetterExample.zip

Theodora Fragkouli

Theodora has graduated from Computer Engineering and Informatics Department in the University of Patras. She also holds a Master degree in Economics from the National and Technical University of Athens. During her studies she has been involved with a large number of projects ranging from programming and software engineering to telecommunications, hardware design and analysis. She works as a junior Software Engineer in the telecommunications sector where she is mainly involved with projects based on Java and Big Data technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
saroj kumar
saroj kumar
6 years ago

seriously this was the first post from where I started learning spring hats off to Theodora Fragkouli for your simple examples, I wonder why no one has commented on this?

Back to top button