The Spring framework enables automatic dependency injection. In other words, by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean Autowiring.
Now, let me explain this in simple language. Autowired provide us the object initialization.
Suppose, I have a Controller class called as UserController and a helper class called UserDaoService where I can write all the methods needed for UserController.
Now, I’ll annotate the helper class UserDaoService as @Component. I have created 3 methods in the helper class UserDaoService which are findAll(), save() and getOne().
Using findAll(), I will get data of all the users and in save() I will add the user in the list and findOne() will find a particular user from the list.
Objects in Spring Container is called Beans. When a class is annotated as @Component, it will create an object (bean) for that class. Here, in our example when we have annotated UserDaoService as @component , so at the time of application is in run mode it will create a bean for UserDaoService class in spring container.
In our controller class (UserController) there is dependency for Helper class (UserDaoService), so how our controller class beans know that there is helper class bean present in container. We need to told controller class bean to find out helper class bean and use it, so here @Autowired comes in picture. It will start to find bean for helper class and inject it into that variable so your variable in Initialized and ready to use.
Controller Class (UserResource)
@RestController
public class UserController
{
@Autowired
private UserDaoService service;
@GetMapping("/users")
public List<User> retriveAllUsers()
{
return service.findAll();
}
}
Helper Class (UserDaoService)
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Component;
@Component
public class UserDaoService
{
public static int usersCount=5;
//creating an instance of ArrayList
private static List<User> users=new ArrayList<>();
//static block
static
{
//adding users to the list
users.add(new User(1, "John", new Date()));
users.add(new User(2, "Tom", new Date()));
users.add(new User(3, "Perry", new Date()));
}
//method that retrieve all users from the list
public List<User> findAll()
{
return users;
}
//method that add the user in the list
public User save(User user)
{
if(user.getId()==null)
{
//increments the user id
user.setId(++usersCount);
}
users.add(user);
return user;
}
//method that find a particular user from the list
public User findOne(int id)
{
for(User user:users)
{
if(user.getId()==id)
return user;
}
return null;
}
}
In the above example, UserDaoService is Autowired in UserController class using by property. Using Autowired, I have called method findAll().
@Autowired
private UserDaoService service;
Use of @Autowired in Integration Testing of SpringBoot Application
Lets imagine a condition where different tests need to have a common test step. Suppose I have created 2 feature files where 1 feature file contain the tests related to valid Request/Response and another feature file create test scenarios related to various service errors. In both the cases, a test step where we have to send an access token to the requests is common. If I create this step in both StepDefinition files, it is duplicacy of code. To avoid this situation, we can create a Helper Class name as CommonStepDefinitions and declare it as @Componenet and @Autowired this helper class to specific StepDefinition class.
In the below example, I have created an access Token and I need to pass this access Token to the SpringBoot request to proceed further. I have @Autowired the CommonDefinition class to ValidRequestDefinitions and get the value of access token here and pass it to the request.
CommonStepDefinitions.class
@Component
@SpringBootTest
public class CommonStepDefinitions {
@Given("^I generate an auth token to pass bearer token to request$")
public String generateToken() throws JSONException {
validatableResponse = given().auth().basic(username, password).param("grant_type", grant_type).when()
.post(authUrl).then();
JSONObject token = new JSONObject(validatableResponse.extract().asString());
accessToken = token.get("access_token").toString();
return accessToken;
}
Main StepDefinition.class (ValidRequestDefinitions)
@SpringBootTest
public class ValidRequestDefinitions{
private ValidatableResponse validatableResponse;
private String bearerToken ;
//Autowired on Property
@Autowired
CommonStepDefinitions helper;
@When("^I send a valid request to the URL (.*)$")
public void sendRequestToGenerateProcess(String endpoint) {
bearerToken = helper.generateToken();
validatableResponse = given().header("Authorization", "Bearer " + bearerToken).contentType(ContentType.JSON)
.body(toString()).when().get(endpoint).then();
}
That’s it! Congratulations on making it through this tutorial and hope you found it useful! Happy Learning!!