X

Spring Dependency Injection using Constructor Injection and Java Configuration

In this blog post, I am going to explain how to use dependency injection in spring using constructor injection and Java configuration. This blog post assumes you already have Java and Maven installed. Step 1: Create a Java Project using Maven Step 2: Let’s create some placeholder folders Step 3: Create the model class src/main/java/com/mycompany/productstore/model/Product.java…

In this blog post, I am going to explain how to use dependency injection in spring using constructor injection and Java configuration. This blog post assumes you already have Java and Maven installed.

Step 1: Create a Java Project using Maven


mvn archetype:generate \
  -DgroupId=com.mycompany.productstore \
  -DartifactId=product_store_java_constructor_injection \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DinteractiveMode=false

Step 2: Let’s create some placeholder folders


cd product_store_java_constructor_injection/src/main

cd java/com/mycompany/productstore

mkdir model service repository

Step 3: Create the model class

src/main/java/com/mycompany/productstore/model/Product.java


package com.mycompany.productstore.model;

public class Product {

  private String name;
  private double price;
  private int quantity;

  public Product(String name, double price, int quantity) {
    this.name = name;
    this.price = price;
    this.quantity = quantity;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public double getPrice() {
    return price;
  }

  public void setPrice(double price) {
    this.price = price;
  }

  public int getQuantity() {
    return quantity;
  }

  public void setQuantity(int quantity) {
    this.quantity = quantity;
  }
}

Step 4: Create a repository interface and its implementation class

src/main/java/com/mycompany/productstore/repository/ProductRepository.java


package com.mycompany.productstore.repository;

import com.mycompany.productstore.model.Product;

import java.util.List;

public interface ProductRepository {

  List<Product> getAllProducts();

}  
  

src/main/java/com/mycompany/productstore/repository/ProductRepositoryImpl.java


package com.mycompany.productstore.repository;

import com.mycompany.productstore.model.Product;

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

public class ProductRepositoryImpl implements ProductRepository {

  public List<Product> getAllProducts() {

    List<Product> productList = new ArrayList<Product>();

    productList.add(new Product("Laptop", 100, 2));
    productList.add(new Product("Phone", 250, 3));
    productList.add(new Product("Keyboard", 50, 1));

    return productList;
  }

}

Generally, in business applications, the repository implementation class connects to the database. But for the simplicity of this blog post, I am returning some hardcoded values.

Step 5: Create a service interface and its implementation class

src/main/java/com/mycompany/productstore/service/ProductService.java


package com.mycompany.productstore.service;

import com.mycompany.productstore.model.Product;

import java.util.List;

public interface ProductService {

  List<Product> getAllProducts();

}

src/main/java/com/mycompany/productstore/service/ProductServiceImpl.java


package com.mycompany.productstore.service;

import com.mycompany.productstore.model.Product;
import com.mycompany.productstore.repository.ProductRepository;

import java.util.List;

public class ProductServiceImpl implements ProductService {

  private ProductRepository productRepository;

  public ProductServiceImpl(ProductRepository productRepository) {
    this.productRepository = productRepository;
  }

  public List<Product> getAllProducts() {
    return productRepository.getAllProducts();
  }
}

The ProductServiceImpl class is dependent on ProductRepository object to get the products, instead of creating an object for its implementation class ProductRepositoryImpl we are passing the ProductRepository object as a parameter to ProductServiceImpl class constructor. In the next steps, we use spring dependency injection to inject the object of ProductRepositoryImpl into ProductService class using its constructor.

Step 6: Add the spring (spring-context) to our project in the pom.xml file


<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
            xmlns="http://maven.apache.org/POM/4.0.0" 
            xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                                http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.productstore</groupId>
  <artifactId>product_store_java_constructor_injection</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>product_store_java_constructor_injection</name>
  <url>http://maven.apache.org</url>

  <dependencies>

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

    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>

  </dependencies>

</project>

The spring-context jar is enough to use the dependency injection.

Step 7: Let’s a AppConfig.java file to create the beans configuration using Java

src/main/java/com/mycompany/productstore/AppConfig.java


package com.mycompany.productstore;

import com.mycompany.productstore.repository.ProductRepository;
import com.mycompany.productstore.repository.ProductRepositoryImpl;
import com.mycompany.productstore.service.ProductService;
import com.mycompany.productstore.service.ProductServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AppConfig {

  @Bean(name = "productRepository")
  public ProductRepository getProductRepository() {
    return new ProductRepositoryImpl();
  }

  @Bean(name = "productService")
  public ProductService getProductService() {
    ProductServiceImpl productService = new ProductServiceImpl(getProductRepository());
    return productService;
  }

}

In the above bean configuration first, we annotated the AppConfig class (it is replacing the XML configuration) using spring @Configuration annotation. Next, we created ProductRepositoryImpl bean and using getProductRepository() method, and annotated it with spring @Bean annotation. Finally, we created ProductServiceImpl bean using getProductService() method and annotated it with spring @Bean annotation. As ProductServiceImpl class dependent on ProductRepositoryImpl object, we passed it as dependency using setProductRepository() setter method.

The @Configuration annotation indicates that the Spring IoC container can use the class as a source of bean definitions.
The @Bean annotation indicates method will return an object that should be registered as a bean in the Spring application context.

Step 8: Let’s the spring ApplicationContext to test whether we can get the beans dynamically and it whether the dependencies are injected or not.

src/main/java/com/mycompany/productstore/App.java


package com.mycompany.productstore;

import com.mycompany.productstore.model.Product;
import com.mycompany.productstore.service.ProductService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

public class App {

  public static void main(String[] args) {

    ApplicationContext appContext = new AnnotationConfigApplicationContext(AppConfig.class);

    ProductService productService = appContext.getBean(ProductService.class);

    List<Product> productsList = productService.getAllProducts();

    System.out.println("---- Products ----");

    for (Product product : productsList) {
      System.out.println(product.getName());
    }

  }
}
       

We created the spring application context using beans configuration created in AppConfig.java, and then we are using getBean() method to get the ProductService object. At this stage spring already created the ProductRepositoryImpl object, ProductServiceImpl object and injected the ProductRepositoryImpl object into the ProductService interface constructor method.

Step 9: Let’s compile and run the application


mvn compile

mvn exec:java -Dexec.mainClass=com.mycompany.productstore.App
    

If there are no errors, we should see the list of products in the console.

When we are building the spring web applications, REST services we don’t explicitly include the spring-context jar, the other spring jars libraries includes it as a transitive dependency.

Categories: JAVA
Shravan Kumar Kasagoni:

View Comments (1)

  • hi
    This helped me to understand collection list can u post the the similar example using cllection Map