The Spring Framework offers the org.springframework.stereotype package, housing annotations that you can use to identify classes as Spring components. These annotations provide extra information about a class's role within an application, which the Spring Framework uses to automatically manage and configure the component. In this article, you'll explore the org.springframework.stereotype package and the @Component, @Controller, @Service, and @Repository annotations more closely.
Spring stereotype annotations
What are stereotype annotations?
Stereotype annotations are special annotations that define a class's role in a Spring application. They come in handy to improve configuration simplicity and boost readability.
Although you can apply stereotype annotations to any class, they mostly end up decorating classes representing Spring components, known as Spring components.
Spring offers a variety of stereotype annotations, including:
- @Component: Use this annotation to define a class as a Spring component.
- @Repository: This annotation identifies a class as a data repository.
- @Service: You use this annotation to mark a class as a service.
- @Controller: This annotation signifies a class as an HTTP controller.
How do you employ stereotype annotations?
To use a stereotype annotation, you add it to the class definition. For instance, to deem a class as a Spring component, you would include the following annotation:
Java
import org.springframework.stereotype.Component
@Component
public class MyClass {
// ...
}Kotlin
import org.springframework.stereotype.Component
@Component
class MyClass {
// ...
}Now let's review examples of stereotype annotation usage:
@Component annotation
The most general stereotype annotation in Spring Boot is the @Component annotation. You can use it to mark any class for management by Spring. This signifies that Spring will automatically generate an instance of the class and inject all dependencies it needs.
For instance, if you have a class that doesn't fall under the web application layer or more specific categories, tagging it with the
@Componentannotation enables Spring to automatically create an instance of the class when the application starts. You can then insert this class into other application components.
Put simply, the @Component annotation is a tool you can use to simplify the configuration and management of Spring components. It's also an effective way to make your code more modular, reusable, and testable.
Here is an example of how to use the @Component annotation:
Java
import org.springframework.stereotype.Component
@Component
public class Dragon {
public String slayDragon() {
return "Rooooaaar!";
}
}Kotlin
import org.springframework.stereotype.Component
@Component
class Dragon {
fun slayDragon(): String {
return "Rooooaaar!"
}
}This code commands Spring to create an instance of the Dragon class and oversee it. We can now inject the Dragon class into other classes and use it as much as we desire.
We could create a Knight class, for instance, that injects the Dragon class and uses it to slay the dragon.
Java
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
@Component
public class Knight {
private final Dragon dragon;
@Autowired
public Knight(Dragon dragon) {
this.dragon = dragon;
}
public void slayDragon() {
System.out.println(dragon.slayDragon());
System.out.println("The knight slays the dragon!");
}
}Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
@Component
class Knight @Autowired constructor(private val dragon: Dragon) {
fun slayDragon() {
println(dragon.slayDragon())
println("The knight slays the dragon!")
}
}Now when we introduce the Knight class into another class, using the @Controller annotated class as an example:
Java
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
@Controller
public class RoarController {
private final Knight knight;
@Autowired
public RoarController(Knight knight) {
this.knight = knight;
}
// ... some methods
}Kotlin
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Controller
@Controller
class RoarController @Autowired constructor(private val knight: Knight) {
// ... some methods
}In this example adding the line
knight.slayDragon();inside any method body will display the following result in the console when executed:
Rooooaaar!
The knight slays the dragon!The "RoarController" class that hosts the @Controller annotation is next. However, it's necessary first to comprehend the scenario.
We've discerned that a class with the @Component annotation is a Spring component in need of creation and addition to the application container. This enables us to invoke the "Knight" class's method and also utilize the "Dragon" class's method.
This basic example unrelated to business logic clarifies the use of the @Component annotation.
A software application's business logic is the part that implements the business rules and processes. It handles data processing, decision-making, and the execution of operations related to the application's business requirements.
In the Spring context, business logic typically takes the form of services. Services, as Spring components accountable for delivering business functionality, usually interact with data sources, including databases or files, and perform business calculations and operations.
@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
@Controllerannotation 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 aGETrequest, returning the response body:Hello, World!. For illustration, let's assume this is your website -https://my-site.com/. Following the linkhttps://my-site.com/homewill 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.
@Controllerand@Component, as discussed, are annotations symbolizing classes usable in web applications. Both inherit from the@Componentannotation, which is common to all Spring Framework components performing similar roles but serve distinct purposes.@Controllersignals that the class is meant to handle HTTP requests. This means classes bearing the@Controllerannotation usually have methods matching HTTP methods like GET, POST, PUT, and DELETE.On the other hand,
@Componentdoes not enforce any predetermined utilization conventions on the class. It would be advisable to pragmatically apply the@Componentannotation, so respond to the question "can@Componentbe 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 executing 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 application parts, such as repositories and other services to send, process, and receive data. The @Service annotation contributes to better code organization and simplifies testing as you can conveniently replace real services with mock objects during unit testing.
A solid example of utilizing 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
MyServiceclass 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 the @Service and @Component in the Spring Framework. As with @Controller, the 'What's the difference? And is it possible to use @Component instead of @Service' query 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, it's recommended to use
@Serviceas it allows for a clearer explanation of the class's purpose. If, however, 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@Componentinterchangeably. Although you can use@Componentinstead 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. This is frequently used 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
MyRepositoryclass carries the@Repositoryannotation. This informs the Spring Framework that theMyRepositoryclass will handle data store interactions forMyEntityobjects.
Addressing whether you can use @Component over @Repository in this context, it will indeed be less informative from the standpoint of the semantics of your code. To articulate that a class is a data repository, using @Repository enhances your code's readability, particularly in expansive applications. Hence, it's ideal to use @Repository for data access data repositories.
Benefits of using stereotype annotations
Utilizing stereotype annotations brings several benefits, including:
Simplified configuration: The use of stereotype annotations simplifies the configuration of Spring components. The Spring Framework can detect and configure stereotype annotations automatically without demanding additional configuration.
Modularity and reusability: Stereotype annotations introduce modularity and reusability into your code. These annotations allow you to compartmentalize your application into different layers, such as the presentation layer, the service layer, and the data access layer, making the code more comprehensible, maintainable, and testable.
Improved structure: Stereotype annotations aid in enhancing the structure of your application. These annotations allow you to clearly define each class's role within your application, simplifying automatic scanning and configuration of Spring beans. This contributes to a more arranged and navigable application.
Conclusion
Stereotype annotations are a professional tool for improving the quality and maintainability of Spring applications. Using stereotype annotations simplifies configuration, reinforces modularity and reusability, and amplifies your application's structure.
Let's recap - In most cases, specialized annotations such as @Service, @Repository, and @Controller provide clearer and more descriptive semantic meaning to the classes in your application. Consider carefully and justify well before using the @Component annotation. Based on the "Dragon" class example, it's now evident that "you can growl, but is it correct?".