Spring Boot - Dependency Injection and Spring Beans
Last Updated :
28 Aug, 2024
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.
Step 2: Add Dependencies
Add the following dependencies into the Spring Boot project.
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:
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.
Step 9: Test the Application
Now, we will test the endpoint in the browser and see the output below:
http://localhost:8080/greet
Output:
This project demonstrates the Dependency Injection and Spring Beans of the Spring Boot Application.