🚀 Introduction: What is @Service
in Spring Boot?
In Spring Boot, the @Service
annotation is used to define service-layer components that contain business logic. It is a specialized version of @Component
, making it easier to recognize service classes in a Spring application.
✅ Key Features of @Service
:
✔ Defines business logic in a Spring Boot application.
✔ Works with dependency injection to manage service beans.
✔ Helps separate the service layer from controllers and repositories.
✔ Provides better readability and maintainability in large projects.
📌 In this guide, you’ll learn:
✅ How @Service
works in Spring Boot.
✅ How it differs from @Component
and @Repository
.
✅ Best practices for structuring the service layer.
1️⃣ Basic Example: Using @Service
in a Spring Boot Application
📌 Example: Creating a UserService
to Manage Users
1. Service Layer (UserService.java
)
@Service
public class UserService {
private final Map<Integer, String> users = new HashMap<>(Map.of(
1, "Ramesh",
2, "Suresh"
));
public String getUserById(int id) {
return users.getOrDefault(id, "User not found");
}
}
2. Controller Layer (UserController.java
)
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public String getUserById(@PathVariable int id) {
return userService.getUserById(id);
}
}
📌 GET Request (GET /api/users/1
)
📌 Response:
Ramesh
✅ The @Service
annotation tells Spring that UserService
is a service-layer component.
✅ Spring Boot automatically manages the bean and injects it into the controller.
2️⃣ Difference Between @Service
, @Component
, and @Repository
@Component
public class UserService {
public String getUserById(int id) {
return "User " + id;
}
}
✅ @Component
works, but @Service
is preferred for clarity.
✅ Spring Boot doesn’t treat @Service
differently, but using it improves code readability.
3️⃣ Injecting Dependencies into @Service
Using @Autowired
There are three ways to inject dependencies into a service:
✅ 1. Constructor-Based Injection (Recommended)
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
✅ Best practice since Spring 4.3 (no need for @Autowired
if there’s only one constructor).
✅ 2. Field Injection (Not Recommended)
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
❌ Not recommended because it makes unit testing harder.
✅ 3. Setter-Based Injection (Use Only When Needed)
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
✅ Useful if dependency injection is optional or needs to be changed dynamically.
4️⃣ Using @Service
with a Repository (Spring Data JPA
)
📌 Example: Connecting UserService
with a Database
1. Repository Layer (UserRepository.java
)
public interface UserRepository extends JpaRepository<User, Integer> {
}
2. Service Layer (UserService.java
)
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUserById(int id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found with ID: " + id));
}
}
3. Controller Layer (UserController.java
)
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable int id) {
return ResponseEntity.ok(userService.getUserById(id));
}
}
📌 GET Request (GET /api/users/1
)
📌 Response (HTTP 200 OK
with JSON Data):
{
"id": 1,
"name": "Ramesh",
"email": "ramesh@example.com"
}
✅ The service layer retrieves data from the repository and sends it to the controller.
✅ This ensures a clean separation of concerns in the application.
5️⃣ Handling Exceptions in @Service
Classes
📌 Example: Throwing a Custom Exception from a Service
@ResponseStatus(HttpStatus.NOT_FOUND)
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(String message) {
super(message);
}
}
📌 Using the Exception in UserService
public User getUserById(int id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found with ID: " + id));
}
📌 GET Request (GET /api/users/99
- Non-Existing User)
📌 Response (HTTP 404 Not Found
):
{
"error": "User not found with ID: 99"
}
✅ Ensures clean error handling with meaningful HTTP status codes.
🎯 Summary: Best Practices for Using @Service
✅ Use @Service
for business logic instead of @Component
.
✅ Follow the layered architecture: Controller → Service → Repository.
✅ Use constructor injection for dependencies (avoid field injection).
✅ Handle exceptions properly using @ResponseStatus
and @ControllerAdvice
.
✅ Ensure service methods follow single-responsibility and reusable logic.
🚀 Following these best practices ensures scalable, maintainable Spring Boot applications!
Comments
Post a Comment
Leave Comment