Annotation Based Spring Config and Auto Wiring

In this example, I’ll show how to do an Annotation Based Spring configuration to define beans and auto wire them together.

Use Case

The Use Case we are going to work on is to fetch list of employees from a service. The service inturn fetch it from data access object.

Creating a Maven Project

First create a simple Maven project by skipping archtype selection in STS.

Add below pom.xml file which can be found at the root of the project.

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.techstackjournal</groupId>
	<artifactId>annotation-based</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.3.2.RELEASE</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.2</version>
				<configuration>
					<source>1.8</source>
					<target>1.8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Creation of Model Class

We need a POJO class to instantiate multiple employee objects which are queried from database.

package com.techstackjournal.model;

public class Employee {

	private String employeeId;
	private String firstName;
	private String lastName;
	private String email;
	
	public Employee() {
		// TODO Auto-generated constructor stub
	}
	
	public Employee(String employeeId, String firstName, String lastName, String email) {
		super();
		this.employeeId = employeeId;
		this.firstName = firstName;
		this.lastName = lastName;
		this.email = email;
	}

	public String getEmployeeId() {
		return employeeId;
	}

	public void setEmployeeId(String employeeId) {
		this.employeeId = employeeId;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	@Override
	public String toString() {
		return "Employee [employeeId=" + employeeId + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email
				+ "]";
	}
	
}

Creating a Data Access Layer

In this data access layer, we will take code to interface approach while creating the EmployeeDAO and its implementation EmployeeDAOImpl.

package com.techstackjournal.dao;

import java.util.List;

import com.techstackjournal.model.Employee;

public interface EmployeeDAO {

	List<Employee> findAll();

}

Since this class supposedly fetch data from database, we annotate this class with @Repository annotation, though we will be just mocking the data for simplicity and to focus on the subject.

package com.techstackjournal.dao;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;

import com.techstackjournal.model.Employee;

@Repository("employeeDao")
public class HibernateEmployeeDAOImpl implements EmployeeDAO {
	public List<Employee> findAll() {
		List<Employee> employees = new ArrayList<Employee>();
		employees.add(new Employee("1", "John", "Doe", "john.doe@techstackjournal.com"));
		employees.add(new Employee("2", "Jane", "Doe", "jane.doe@techstackjournal.com"));
		return employees;
	}
}

Creating Service Layer

Similar to the data access layer, in service layer too we will code to interfaces. We’ll be creating EmployeeService which demands the findAll method to be implemented. The EmployeeServiceImpl implements this class and provides the implementation to findAll method.

package com.techstackjournal.service;

import java.util.List;

import com.techstackjournal.model.Employee;

public interface EmployeeService {

	List<Employee> findAll();

}

Service Implementation and Autowire on Member

Since this class acts as the placeholder for the business logic, we will annotate this class using @Service annotation.

See also  Java based Spring Configuration

This class needs an instance of EmployeeDAO. As you must be knowing, we can provide the dependencies in 3 ways using annotations. In this particular code snippet, we will provide the dependency through annotating the member variable using @Autowired. You can find other 2 approaches at the end of this article.

package com.techstackjournal.service;

import java.util.List;

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

import com.techstackjournal.dao.EmployeeDAO;
import com.techstackjournal.model.Employee;

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

	@Autowired
	private EmployeeDAO employeeDao;

	public EmployeeServiceImpl(EmployeeDAO employeeDao) {
		this.employeeDao = employeeDao;
		System.out.println("constructor injection " + employeeDao);
	}

	public List<Employee> findAll() {
		return employeeDao.findAll();
	}

	public void setEmployeeDao(EmployeeDAO employeeDao) {
		System.out.println("setter injection " + employeeDao);
		this.employeeDao = employeeDao;
	}

}

Creating Application Context XML

Inside the applicationContext.xml file, with the help of <context:annotation-config /> tag, we tell Spring that we are using Annotation Configuration to define Spring beans.

Using <context:component-scan /> tag, we tell Spring where to look for Spring beans. We specify the package location to scan using base-package attribute. If you want Spring to scan only selected packages, you can write all of them separating them with a comma.

<?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.xsd
	http://www.springframework.org/schema/context 
		http://www.springframework.org/schema/context/spring-context.xsd">

	<context:annotation-config />
	<context:component-scan
		base-package="com.techstackjournal" />

</beans>

Application Class

In this application class, we get the list of employees from the EmployeeService object, which we obtain from ApplicationContext.

package com.techstackjournal.app;

import java.util.List;

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

import com.techstackjournal.model.Employee;
import com.techstackjournal.service.EmployeeService;

public class Application {

	public static void main(String[] args) {

		ApplicationContext appContext = new ClassPathXmlApplicationContext("applicationContext.xml");

		EmployeeService service = appContext.getBean("employeeService", EmployeeService.class);

		List<Employee> employees = service.findAll();

		for (Employee employee : employees) {
			System.out.println(employee);
		}

	}

}

Autowire using Setter Method

In the above example, we saw the auto wiring using member. In this example, we’ll explore the setter method injection of dependencies.

To enable the setter injection, we need to provide a setter method that initialize the dependency, in our case it’s EmployeeDAO and annotate that setter method using @Autowired annotation within EmployeeServiceImpl class.

package com.techstackjournal.service;

import java.util.List;

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

import com.techstackjournal.dao.EmployeeDAO;
import com.techstackjournal.model.Employee;

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

	private EmployeeDAO employeeDao;

	public List<Employee> findAll() {
		return employeeDao.findAll();
	}

	@Autowired
	public void setEmployeeDao(EmployeeDAO employeeDao) {
		this.employeeDao = employeeDao;
	}

}

Output:

Employee [employeeId=1, firstName=John, lastName=Doe, email=john.doe@techstackjournal.com]
Employee [employeeId=2, firstName=Jane, lastName=Doe, email=jane.doe@techstackjournal.com]

Autowire using Constructor

To Autowire using a constructor, firstly we need to add a constructor which takes the dependency as an argument and initialize it within its body, secondly you need to add the @Autowired annotation to the constructor.

See also  Autowire using Java Based Spring Configuration

However, starting from Spring 4.3 onwards, if you have only 1 constructor in the class, auto wiring will happen implicitly.

Implicit Constructor Injection

Since we have only 1 constructor in the below version of EmployeeServiceImpl, implicit constructor injection will take place to fulfill the dependency of EmployeeServiceImpl by providing it EmployeeDAO bean.

package com.techstackjournal.service;

import java.util.List;

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

import com.techstackjournal.dao.EmployeeDAO;
import com.techstackjournal.model.Employee;

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

	private EmployeeDAO employeeDao;

	public EmployeeServiceImpl(EmployeeDAO employeeDao) {
		this.employeeDao = employeeDao;
	}

	public List<Employee> findAll() {
		return employeeDao.findAll();
	}
}

Explicit Constructor Injection

Since we have 2 constructors in the below version of EmployeeServiceImpl, we must explicitly tell Spring Container which constructor it should use to fulfill the dependencies. As the second constructor with EmployeeDAO argument is the one that we need for constructor injection, we define that constructor with @Autowired annotation.

package com.techstackjournal.service;

import java.util.List;

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

import com.techstackjournal.dao.EmployeeDAO;
import com.techstackjournal.model.Employee;

@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

	private EmployeeDAO employeeDao;

	public EmployeeServiceImpl() {

	}
	
	@Autowired
	public EmployeeServiceImpl(EmployeeDAO employeeDao) {
		this.employeeDao = employeeDao;
		System.out.println("constructor injection " + employeeDao);
	}

	public List<Employee> findAll() {
		return employeeDao.findAll();
	}

}