Open In App

Spring Boot - Dependency Injection and Spring Beans

Last Updated : 28 Aug, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

Spring Boot is a powerful framework for building RESTful APIs and microservices with minimal configuration. Two fundamental concepts within Spring Boot are Dependency Injection (DI) and Spring Beans. Dependency Injection is a design pattern used to implement Inversion of Control (IoC), allowing the framework to manage object creation and dependencies. Spring Beans are objects managed by the Spring IoC container, forming the backbone of any Spring application.

Dependency Injection and Spring Beans

Dependency Injection (DI)

Dependency Injection is a design pattern that allows the creation of dependent objects to be managed by an external source rather than the object managing its dependencies itself. This pattern promotes loose coupling, enhancing flexibility and making code easier to maintain and test.

In a Spring application, Dependency Injection can be achieved in three main ways:

1. Constructor Injection

Dependencies are provided through the class constructor. This method ensures that dependencies are provided at the time of object creation, making the object immutable.

Example:

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

@Service
public class MyServiceClass {
    private final Dependency dependency;

    // Constructor Injection
    @Autowired
    public MyServiceClass(Dependency dependency) {
        this.dependency = dependency;
    }

    // Getter method (optional)
    public Dependency getDependency() {
        return dependency;
    }
}
  • @Service: Marks this class as a Spring Bean.
  • @Autowired: Injects the Dependency object into the constructor.
  • Constructor injection ensures that the dependency is required for the object to be created.

2. Setter Injection

Dependencies are provided through setter methods. This method allows for optional dependencies and the ability to change dependencies after the object is created.

Example:

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

@Service
public class MyService {
    private Dependency dependency;

    // Setter Injection
    @Autowired
    public void setDependency(Dependency dependency) {
        this.dependency = dependency;
    }

    // Getter method (optional)
    public Dependency getDependency() {
        return dependency;
    }
}
  • @Service: Marks this class as a Spring Bean.
  • @Autowired: Injects the Dependency object into the setter method.
  • Setter injection allows the dependency to be set after object creation.

3. Field Injection

Dependencies are directly injected into fields using annotations like @Autowired. This method is concise but generally discouraged as it hides dependencies, making the code less clear and harder to test.

Example:

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

@Service
public class MyService {
    // Field Injection
    @Autowired
    private Dependency dependency;

    // Getter method (optional)
    public Dependency getDependency() {
        return dependency;
    }
}
  • @Service: Marks this class as a Spring Bean.
  • @Autowired: Injects the Dependency object directly into the field.
  • Field injection can make the code harder to test and maintain due to the lack of visibility of dependencies.

Spring Beans

Spring Beans are objects managed by the Spring IoC container. A bean is typically an instance of a class that is managed by Spring, and its lifecycle (creation, initialization, and destruction) is managed by the container. Beans can be configured using annotations or XML configuration files.

Defining Beans:

1. Using the Annotations

  • @Component: A general-purpose annotation to mark a class as a Spring Bean.
  • @Service: Specialized for service-layer classes.
  • @Repository: Specialized for persistence-layer classes.
  • @Controller: Specialized for controller classes in Spring MVC.

Example:

@Service
public class MyService {
    public String serve() {
        return "Service is running!";
    }
}
  • @Service: Marks this class as a Spring Bean specifically for the service layer.
  • The serve method provides functionality for the service.

2. Using the @Bean Annotation

Beans can also be defined using the @Bean annotation within a configuration class. This method provides more control over the bean creation process.

Example:

@Configuration
public class AppConfig {

    // Define a bean of type MyService
    @Bean
    public MyService myService() {
        return new MyService();
    }
}
  • @Configuration: Indicates that this class contains bean definitions.
  • @Bean: Defines a bean method, allowing more control over bean creation.

Bean Scopes:

Spring supports several bean scopes:

  • Singleton: A single instance of the bean is created and shared across the application.
  • Prototype: A new instance of the bean is created each time it is requested.
  • Request: A single instance of the bean is created for each HTTP request, typically used in web applications.
  • Session: A single instance is created for each HTTP session (used in web applications).

Step-by-step Implementation with Example

Let's create a simple Spring Boot project to demonstrate Dependency Injection and Spring Beans.

Step 1: Create the Spring Boot Project

Create a new Spring Boot project using IntelliJ IDEA with the following options:

  • Name: spring-inject-demo
  • Language: Java
  • Type: Maven
  • Packaging: Jar

Click on the Next button.

Project Metadata

Step 2: Add Dependencies

Add the following dependencies into the Spring Boot project.

Add Dependencies
  • spring-boot-starter-web: Includes dependencies for building web applications.
  • spring-boot-devtools: Provides development-time tools like automatic restarts.
  • lombok: A library that reduces boilerplate code (optional).
  • spring-boot-starter-test: Provides testing dependencies.

Project Structure

After creating the project, the file structure will look like this:

Project Folder Structure

Step 4: Define the Service Interface

Create an interface named GreetingService to define a method for greeting.

Java
package com.gfg.springinjectdemo;

public interface GreetingService {
    String greet();
}

This interface defines a single method greet, which will be implemented by service classes.

Step 5: Implement the Service Interface

Create a class EnglishGreetingService that implements the GreetingService interface.

Java
package com.gfg.springinjectdemo;

import org.springframework.stereotype.Service;

@Service
public class EnglishGreetingService implements GreetingService {
    @Override
    public String greet() {
        return "Hello, World!";
    }
}

Explanation:

  • @Service: Marks this class as a Spring Bean and registers it with the Spring context.
  • greet(): Provides a greeting message.

Step 6: Create the Controller to Use the Service

Create a GreetingController to use the GreetingService.

Java
package com.gfg.springinjectdemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private final GreetingService greetingService;

    // Constructor Injection
    @Autowired
    public GreetingController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    // Endpoint to return greeting message
    @GetMapping("/greet")
    public String greet() {
        return greetingService.greet();
    }
}

Explanation:

  • @RestController: Marks this class as a REST controller.
  • @Autowired: Injects the GreetingService into the constructor.
  • @GetMapping("/greet"): Maps the /greet URL to the greet method, which returns the greeting message.

Step 7: Main Class

The main class remains unchanged.

Java
package com.gfg.springinjectdemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringInjectDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringInjectDemoApplication.class, args);
    }
}
  • @SpringBootApplication: Indicates that this is a Spring Boot application.
  • main(): The entry point of the application.

pom.xml file:

XML
<?xml version="1.0" encoding="UTF-8"?>
<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>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.2</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.gfg</groupId>
	<artifactId>spring-inject-demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-inject-demo</name>
	<description>spring-inject-demo</description>
	<url/>
	<licenses>
		<license/>
	</licenses>
	<developers>
		<developer/>
	</developers>
	<scm>
		<connection/>
		<developerConnection/>
		<tag/>
		<url/>
	</scm>
	<properties>
		<java.version>17</java.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

Step 8: Run the application

After completion of the project, now run the application and it will start at port 8080.

Application Started

Step 9: Test the Application

Now, we will test the endpoint in the browser and see the output below:

http://localhost:8080/greet

Output:

Output

This project demonstrates the Dependency Injection and Spring Beans of the Spring Boot Application.


Next Article

Similar Reads