How to implement Dependency Injection using @Autowired Annotation in Spring Boot
In this tutorial we are going to learn about implementing the Dependency Injection and auto wiring the beans using @Autowired Annotation.
@Autowired: Marks a constructor, field, setter method or config method as to be autowired by Spring’s dependency injection facilities. This is an alternative to the JSR-330 javax.inject.Inject annotation, adding required-vs-optional semantics.
What is the need for Dependency Injection?
When building an application ideally all java classes should be independent from each other as much as possible and must be loosely coupled which enables us to reuse and test the classes independently. So, Dependency Injection helps us to achieve the Independency between Java classes.
Look at the below Rest Controller class where it has the POST handler mappings with business logic to perform create operation on user details.
Code Snippet:
@RestController
@RequestMapping("/users")
public class UserController {
HashMap<String, UserModel> user;
@PostMapping(produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, consumes = {
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<UserModel> createUser(@Valid @RequestBody UserModel us) {
UserModel um = new UserModel();
um.setEmail(us.getEmail());
um.setFirstname(us.getFirstname());
um.setLastname(us.getLastname());
um.setUserId(us.getUserId());
if (user == null)
user = new HashMap<>();
user.put(us.getUserId(), um);
return new ResponseEntity<UserModel>(um, HttpStatus.CREATED);
}
}
Ideally while building a RESTful web service application the business logic that is related to create a new user is encapsulated into a separate class like an UserService because this business logic contains much more code which communicate with other classes related to utilities and database to create a new user.
Instead, if we write all our business logic into a single unit or class as shown in the above code snippet it creates a tight coupling so we build our application and segregate the business logic at different layers like service, repository, DAO and create the instances of this classes into the rest controller.
Create a new package called service and create an interface called UserService and define a method signature for createUser method as in the Rest Controller.
Code Snippet:
import com.behindjava.tutorial.model.UserModel;
public interface UserService {
UserModel createUser(UserModel us);
}
Now we need to create the implementation for this interface. So, create a package called serviceImpl and create a class UserSericeImpl as shown below and add the business logic from Rest Controller to here.
Code Snippet:
import org.springframework.stereotype.Service;
import com.behindjava.tutorial.model.UserModel;
import com.behindjava.tutorial.service.UserService;
@Service
public class UserServiceImpl implements UserService {
HashMap<String, UserModel> user;
@Override
public UserModel createUser(UserModel us) {
UserModel um = new UserModel();
um.setEmail(us.getEmail());
um.setFirstname(us.getFirstname());
um.setLastname(us.getLastname());
um.setUserId(us.getUserId());
if (user == null)
user = new HashMap<>();
user.put(us.getUserId(), um);
return um;
}
}
Now in the Rest Controller instead of calling the method from the service implementation class which creates a direct dependency or tight coupling and also testing of these classes i.e., Rest controller and Service implementation is not possible independently.
Code Snippet:
@RestController
@RequestMapping("/users")
public class UserController {
HashMap<String, UserModel> user;
@Autowired
UserService userService;
@PostMapping(produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, consumes = {
MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<UserModel> createUser(@Valid @RequestBody UserModel us) {
// Direct dependency on implementation class
// UserModel um= new UserServiceImpl().createUser(us);
UserModel um =userService.createUser(us);
return new ResponseEntity<UserModel>(um, HttpStatus.CREATED);
}
}
Due to this we are going to use dependency injection and we will auto wire the service interface in our rest controller and create an instance of user service implementation using @Autowired annotation and to make this happen we need to annotate our service implementation class with @service so that spring framework will scan for the packages for this annotation and creates an instance of this class and make it available to classes that need to be auto wired.
You can test this using postman and try to implement the dependency injection for the remaining methods since I have shown in this tutorial only for POST mapping for easy understanding.