Introduction to Basic @Annotations in Spring Boot and Their Uses
When I first started using Spring Boot, I needed help understanding the proper usage of annotations. I don’t want others to face the same challenges, so I’ve written this article to share my insights
Annotations play a crucial role in the Spring Boot framework, as they provide an easy way to configure and customize various aspects of the application. In this article, we’ll explore some of the best practices for using annotations in Spring Boot, so that you can take full advantage of the framework’s capabilities.
Use @SpringBootApplication to bootstrap the application
The @SpringBootApplication annotation is a convenient annotation that combines three other annotations: @Configuration, @EnableAutoConfiguration, and @ComponentScan.
The @Configuration annotation indicates that the class should be considered as a configuration class, where Spring can find and configure beans.
The @EnableAutoConfiguration annotation is a Spring Boot feature that automatically configures the application based on its classpath and other settings.
The @ComponentScan annotation enables component scanning, allowing Spring to discover and instantiate beans based on the specified package or class.
Here is an example of using @SpringBootApplication to bootstrap a Spring Boot application:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class EmailApp{
public static void main(String[] args) {
SpringApplication.run(EmailApp.class, args);
}
}
In the example above, the @SpringBootApplication
annotation is added to the EmailApp
class, which is the main class of the Spring Boot application.
The main
method calls the SpringApplication.run()
method, passing in the EmailApp
class and the command line arguments. This method starts the Spring Boot application, which initializes the Spring context and starts the server.
By using the @SpringBootApplication
annotation, we don't need to write any boilerplate configuration code. Spring Boot will automatically detect and configure the necessary components based on the classpath and other settings.
Use @RestController for RESTful APIs
When building a RESTful API in Spring Boot, the @RestController annotation is the recommended approach to indicate that a controller is responsible for handling HTTP requests. This annotation is a specialization of the @Component annotation and is used to combine the functionality of both the @Controller and @ResponseBody annotations.
The @Controller annotation is used to indicate that a class serves the role of a controller in Spring, while the @ResponseBody annotation is used to indicate that the return value of a method should be bound to the HTTP response body.
To create a basic RESTful API in Spring Boot using the @RestController annotation, you can define a controller class like the following:
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping("/getAll")
public ResponseEntity<List<User>> getUsers() {
}
@GetMapping("{userId}")
public User getUserById(@PathVariable Long userId) {
}
@PostMapping("/create")
public ResponseEntity<User> createUser(@RequestBody createRequest request) {
}
@PatchtMapping("{userId}")
public ResponseEntity<User> updateUser(@PathVariable Long userId, @RequestBody JsonPatch updateRequest) {
}
@DeleteMapping("{userId}")
public ResponseEntity<?> deleteUser(@PathVariable Long userId) {
}
}
In the above example, the @RestController annotation is used to define the UserController class as a RESTful controller. The @RequestMapping annotation is used to define the base URL for all the HTTP requests handled by this controller.
The controller contains five methods, each of which handles a different HTTP request for managing users. The @GetMapping, @PostMapping, @PutMapping, @PatchMapping, and @DeleteMapping annotations are used to handle HTTP GET, POST, PUT, PATCH, and DELETE requests respectively.
The @PathVariable annotation extracts values from the URL and passes them as arguments to the corresponding methods. The @RequestBody annotation is used to extract data from the request body and bind it to a method parameter.
Overall, using the @RestController annotation in Spring Boot makes it easy to build a RESTful API by combining the functionality of both the @Controller and @ResponseBody annotations.
Use @Service for business logic
In a Spring application, it’s common to have a layer of business logic that’s responsible for handling the application’s core functionality. This layer is typically implemented using services, which are classes that contain the actual implementation of the application’s business logic.
To indicate that a class is a service, you should annotate it with the @Service annotation. This annotation is a specialization of the @Component annotation, which is used to indicate that a class is a Spring-managed component.
Here’s an example of a simple service class:
@Service
public class AppUserService {
public RegisterResponse registerUser() {
}
}
In this example, the AppUserService class is annotated with @Service, indicating that it’s a Spring-managed service component. The class contains a single method, registerUser(), which performs some business logic and returns a result.
Once you’ve annotated a class with @Service, you can inject it into other components using Spring’s dependency injection features. For example, you could inject the MyService class into a controller like this:
@RestController
public class AppUserController {
private final AppUserService appUserService;
public MyController(AppUserService appUserService) {
this.appUserService = appUserService;
}
@GetMapping("/getAll")
public ResponseEntity<?> getUsers() {
}
}
Use @Repository for data access
When building an application that requires data access, you’ll often need to create a repository to handle data persistence. The @Repository annotation in Spring is used to indicate that a particular class is a repository.
To use the @Repository
annotation, you first need to create a class that implements a repository interface. For example, let’s say you’re building a simple application that requires user data persistence. You could create a UserRepository interface:
public interface AppUserRepository {
User findById(Long id);
User findByUsername(String username);
List<User> findAll();
void save(User user);
void delete(User user);
}
Then, you can create a class that implements this interface and annotate it with @Repository:
@Repository
public class AppUserRepositoryImpl implements AppUserRepository {
private JdbcTemplate jdbcTemplate;
public AppUserRepositoryImpl(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@Override
public User findById(Long id) {
}
@Override
public User findByUsername(String username) {
}
@Override
public List<User> findAll() {
}
@Override
public void save(User user) {
}
@Override
public void delete(User user) {
}
}
In this example, we’re using Spring’s JdbcTemplate to handle data access. We’ve injected the JdbcTemplate in the constructor of the AppUserRepositoryImpl
class. We’ve then implemented the methods from the AppUserRepository interface to perform CRUD operations on the database.
By annotating the AppUserRepositoryImpl class with @Repository
, we’re indicating to Spring that this class is a repository and should be managed by Spring’s dependency injection container.
It’s important to note that you should not annotate the repository interface with @Repository
. This is because Spring creates a proxy for the repository interface at runtime, and annotating the interface would result in the proxy being annotated as a repository, which is not the intended behaviour.
Use @Autowired for dependency injection
The @Autowired annotation is used to inject dependencies into a class. By using this annotation, you can avoid writing boilerplate code to look up dependencies manually. Spring will automatically scan the classpath and inject the required dependencies.
There are several types of autowiring that can be used with the @Autowired annotation. They include:
- Constructor injection
- Setter injection
- Field injection
Here’s an example of each type of injection:
Constructor injection:
@Service
public class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Setter injection:
@Service
public class UserService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
}
Field injection:
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
}
It’s worth noting that field injection is generally considered to be the least preferred method, as it can make it difficult to write unit tests for the class. Constructor injection is usually the preferred method, as it allows the dependencies to be declared as final and makes it clear which dependencies are required for the class to function. Setter injection can also be useful in some cases, such as when a dependency is optional.
Use @ConfigurationProperties for configuration
The @ConfigurationProperties annotation is used to bind external properties to a class. By using this annotation, you can easily configure your application using external configuration files, such as application.properties or application.yml.
Use @Scheduled for scheduling tasks
The @Scheduled annotation is used to schedule tasks to run at specific intervals. By using this annotation, you can easily schedule background tasks, such as database cleanups or report generation.
To conclude, annotations in Spring Boot provide a powerful means of configuring and customizing applications. By adhering to these best practices, you can fully utilize the framework’s potential and write concise, expressive, and sustainable code. I hope this guide proves useful. Best wishes!