In the previous articles, we saw how to configure the beans based on XML and annotations. In this example, we’ll learn how we can configure beans based Java configuration, a third approach to configure Spring beans. We’ll follow the similar class design by coding to interfaces.
Class Structure
Item
– a POJO class to store item infoItemDAO
– an interface that we will use in a dependent service classItemDAOImpl
– an implementation ofItemDAO
returns list of mocked Item instancesItemService
– an interface that we will use in the application to hold a service instanceItemServiceImpl
– an implementation ofItemService
and the dependent ofItemDAO
instanceApplication
– It will get theItemService
instance to fetch itemsAppConfig
– a configuration class replacing the XML based configuration
Creation of 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>java-config</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>
Right click on the project, and select Maven=>Update Project. This will download all the required jar files for the application.
Creating the Model Class
Let’s create an Item
model class which will hold the instances returned by the DAO layer.
package com.techstackjournal.model;
public class Item {
private String itemId;
private String itemName;
private double price;
public Item() {
}
public Item(String itemId, String itemName, double price) {
super();
this.itemId = itemId;
this.itemName = itemName;
this.price = price;
}
public String getItemId() {
return itemId;
}
public void setItemId(String itemId) {
this.itemId = itemId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Item [itemId=" + itemId + ", itemName=" + itemName + ", price=" + price + "]";
}
}
Data Access Layer
In this layer, we’ll create ItemDAO
interface, which will be implemented by ItemDAOImpl
. Also, ItemServiceImpl
will use ItemDAO
interface to call the findAll
method. We call this approach as coding to interface. With this approach, we can decrease the dependence on the implementation class.
package com.techstackjournal.dao;
import java.util.List;
import com.techstackjournal.model.Item;
public interface ItemDAO {
List<Item> findAll();
}
ItemDAOImpl
implements ItemDAO
and provides a findAll
method. In this findAll
method, we are not writing the actual data access logic to simplify the subject in focus. We’ll just mock the findAll
method by returning a collection object.
package com.techstackjournal.dao;
import java.util.ArrayList;
import java.util.List;
import com.techstackjournal.model.Item;
public class ItemDAOImpl implements ItemDAO {
public List<Item> findAll() {
List<Item> items = new ArrayList<Item>();
items.add(new Item("1", "Mobile", 400));
items.add(new Item("2", "Book", 10));
return items;
}
}
Service Layer
In this Service Layer, we’ll be creating ItemService interface and ItemServiceImpl class.
package com.techstackjournal.service;
import java.util.List;
import com.techstackjournal.model.Item;
public interface ItemService {
List<Item> findAll();
}
ItemServiceImpl
implements ItemService
interface. This class is in HAS-A relation with an object of type ItemDAO
. But you can see that we are not creating any instance of type ItemDAO
. Spring Container will wire the instance of ItemServiceImpl
with the instance of type ItemDAO
either by constructor or by type ItemDAO
or by the name of the reference variable itemDao
.
package com.techstackjournal.service;
import java.util.List;
import com.techstackjournal.dao.ItemDAO;
import com.techstackjournal.model.Item;
public class ItemServiceImpl implements ItemService {
private ItemDAO itemDao;
public ItemServiceImpl() {
}
public ItemServiceImpl(ItemDAO itemDao) {
super();
this.itemDao = itemDao;
}
public List<Item> findAll() {
return itemDao.findAll();
}
public void setItemDao(ItemDAO itemDao) {
this.itemDao = itemDao;
}
}
Main Application
In this class, we’ll be fetching the ItemService
instance from Spring Container using AnnotationConfigApplicationContext
by passing AppConfig.class
as a constructor argument.
package com.techstackjournal.app;
import java.util.List;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.techstackjournal.model.Item;
import com.techstackjournal.service.ItemService;
public class Application {
public static void main(String[] args) {
ApplicationContext appContext = new AnnotationConfigApplicationContext(AppConfig.class);
ItemService service = appContext.getBean("itemService", ItemService.class);
List<Item> items = service.findAll();
for (Item item : items) {
System.out.println(item);
}
}
}
Java based Configuration
Finally, in this class we will define the beans using Java based configuration replacing the Spring XML based configuration (applicationContext.xml
) file. In this class we’ll define 2 beans to get the instances of type ItemDAOImpl
and ItemServiceImpl
, respectively.
Java based Configuration with Constructor Injection
While creating the ItemServiceImpl
bean, we’ll make use of its constructor having ItemDAO
to address the dependency by passing the instance of ItemDAOImpl
.
package com.techstackjournal.app;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.techstackjournal.dao.ItemDAO;
import com.techstackjournal.dao.ItemDAOImpl;
import com.techstackjournal.service.ItemService;
import com.techstackjournal.service.ItemServiceImpl;
@Configuration
public class AppConfig {
@Bean(name = "itemDao")
public ItemDAO getItemDAO() {
return new ItemDAOImpl();
}
@Bean(name = "itemService")
public ItemService getItemService() {
return new ItemServiceImpl(getItemDAO());
}
}
Java based Configuration with Setter Injection
To resolve the dependencies of ItemServiceImpl
using setter injection we’ll change the above getItemService
method as below.
@Bean(name = "itemService")
public ItemService getItemService() {
ItemServiceImpl itemServiceImpl = new ItemServiceImpl();
itemServiceImpl.setItemDao(getItemDAO());
return itemServiceImpl;
}