Computer scienceBackendSpring BootCore container

Spring Stereotypes

12 minutes read

The org.springframework.stereotype package contains annotations that mark a class's role within a Spring application: @Component, @Controller, @Service, and @Repository.

You already met @Component in the previous topic — it's the general-purpose stereotype that makes a class eligible for automatic detection and injection by Spring. @Controller, @Service, and @Repository are all specialized versions of @Component, so everything you learned there (auto-detection, constructor injection, singleton by default) still applies to them.

This topic takes a close look at the three specialized stereotypes — what each one communicates about a class's role, and when to use one instead of plain @Component.

@Controller annotation

The @Controller annotation operates like a bouncer at a club. It checks if a request is legit before letting it into the club (the application). If the request fails the validation, the bouncer (the controller) turns it away.

To put things in professional terms - the @Controller annotation in Spring Boot marks a class as a controller managing HTTP requests.

Example:

Java
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody

@Controller
public class MyController {

    @GetMapping("/hello")
    @ResponseBody
    public String helloWorld() {
        return "Hello, World!";
    }

    // Other methods...
}
Kotlin
import org.springframework.stereotype.Controller
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.ResponseBody

@Controller
class MyController {

    @GetMapping("/hello")
    @ResponseBody
    fun helloWorld(): String {
        return "Hello, World!"
    }

    // Other methods...
}

In this example, the method helloWorld(); is an HTTP response to a GET request, returning the response body: Hello, World!. For illustration, let's assume this is your website - https://my-site.com/. Following the link https://my-site.com/home will display "Hello, World!" on the page.

The methods and business logic can change based on your needs.

You might wonder about the difference between @Controller and @Component or ask yourself whether you can use the second option instead of the first.

  • @Controller and @Component, as discussed, are annotations symbolizing classes usable in web applications. Both inherit from the @Component annotation, which is common to all Spring Framework components performing similar roles but serve distinct purposes.

  • @Controller signals that the class is meant to handle HTTP requests. This means classes bearing the @Controller annotation usually have methods matching HTTP methods like GET, POST, PUT, and DELETE.

  • On the other hand, @Component does not enforce any predetermined utilization conventions on the class. It would be advisable to pragmatically apply the @Component annotation, so respond to the question "can @Component be used instead of @Controller" with an understanding of the difference between "can be used" and "correctly used".

@Service annotation

The @Service annotation in Spring Boot marks a class as a service that executes the application's business logic. By tagging a class with the @Service annotation, Spring will automatically generate that class's instance and include it in its container as a bean.

Services can communicate with other parts of the application, such as repositories and other services, to send, process, and receive data. The @Service annotation helps you organize your code better and simplifies testing since you can conveniently replace real services with mock objects during unit testing.

A solid example of using the @Service annotation would be the following code:

Example:

Java
import org.springframework.stereotype.Service

@Service
public class MyService {

    private String generatePasswordHash(String userPassword) {
        // Implementing Password Hash Generation
        // ...
        return hashedPassword
    }
}
Kotlin
import org.springframework.stereotype.Service

@Service
class MyService {

    private fun generatePasswordHash(userPassword: String): String {
        // Implementing Password Hash Generation
        // ...
        return hashedPassword
    }
}

In this example, the MyService class is a business logic class responsible for hashing the user's password during registration or authorization or for other requirements.

By now, you've probably noticed the similarity in functionality between @Service and @Component in the Spring Framework. As with @Controller, the 'What's the difference? And can I use @Component instead of @Service?' question is relevant.

The answer again lies in semantics. The @Service annotation is part of the aforementioned list of specialized annotations.

  • If a class executes business logic or represents a service, we recommend using @Service because it more clearly explains the class's purpose. However, if you have a class that is neither a service nor has specific business logic, @Component might be a suitable option. In most cases, you can use @Service and @Component interchangeably. Although you can use @Component instead of @Service, the choice depends on your preference and your intention to explicitly convey your code's semantics.

@Repository annotation

The @Repository annotation, a specialized version of @Component, marks classes as repositories for data access. Developers frequently use this to label classes that interact with a database. Along with delivering specific semantics about exception handling related to data access, @Repository catches DataAccessException exceptions and translates them into more informative Spring exceptions.

Example:

Java
import org.springframework.stereotype.Repository

@Repository
public class MyRepository {

    public void save(MyEntity entity) {
        // Implementing Persistence
        // ...
    }

    public MyEntity findById(Long id) {
        // Implementing ID Search
        // ...
    }
}
Kotlin
import org.springframework.stereotype.Repository

@Repository
class MyRepository {

    fun save(entity: MyEntity) {
        // Implementing Persistence
        // ...
    }

    fun findById(id: Long): MyEntity? {
        // Implementing ID Search
        // ...
    }
}

For instance, in the above example, the MyRepository class carries the @Repository annotation. This tells the Spring Framework that the MyRepository class will handle data store interactions for MyEntity objects.

When considering whether you can use @Component instead of @Repository in this context, it will indeed be less informative from the standpoint of the semantics of your code. To show that a class is a data repository, using @Repository improves your code's readability, especially in large applications. Therefore, it's best to use @Repository for data access repositories.

Conclusion

@Controller, @Service, and @Repository are all specialized versions of @Component, each signaling a specific role: handling HTTP requests, executing business logic, or accessing data (with the added benefit of exception translation for @Repository). Using the specific stereotype instead of plain @Component makes your code's intent clearer at a glance, especially in larger applications — reserve @Component for classes that genuinely don't fit any of the three specialized roles.

34 learners liked this piece of theory. 4 didn't like it. What about you?
Report a typo