0

I've seen tutorials where they use different syntax to accomplish the same thing. Once a POST request to create a student object comes in via the controller, the service layer injects the repository using these two methods.

method 1:

@Service
@AllArgsConstructor
@Transactional
public class StudentService {
    private final StudentRepository studentRepo;
    // complete service code using studentRepo
}

As well as Method 2:

@Service
public class StudentService {
    @Autowire
    private StudentRepository studentRepo;
    // complete service code using studentRepo
}

I read that it has something to do with constructor and field injection but I'm seriously not understanding how this syntax addresses the difference. Any explanations or resources for me to better understand? Thank you in advance!

Anshul Sharma
  • 1,018
  • 3
  • 17
  • 39
GioPoe
  • 109
  • 3
  • 12
  • 3
    seems like a duplication of this one: https://stackoverflow.com/questions/40620000/spring-autowire-on-properties-vs-constructor – Yonatan Karp-Rudin Aug 05 '20 at 05:53
  • @paulsm4 could I ask why do you think they don't have similar purpose? I would like to hear what you think of it. I do agree that Yonatan found a duplicate, but the post he links also mentions that these two methods achieve the same goal. – GioPoe Aug 05 '20 at 06:34
  • 1
    @paulsm4, they are. He probably is confused because he doesn’t know about constructor injection and doesn’t see the constructor generated by Lombok – Abhijit Sarkar Aug 05 '20 at 06:36

2 Answers2

6

You are stacking a lot of frameworks which are adding to the confusion. The confusion is probably due to the fact you are using Lombok. The @AllArgsConstructor automatically adds a constructor with all the arguments needed to construct an instance of the service.

@AllArgsConstructor generates a constructor with 1 parameter for each field in your class. Fields marked with @NonNull result in null checks on those parameters. - Source: Lombok Documentation

Using the @AllArgsConstructor effectively generates the following class

@Service
@Transactional
public class StudentService {

    private final StudentRepository studentRepo;

    public StudentService(StudentRepository studentRepo) {
        this.studentRepo=studentRepo;
    }
    // complete service code using studentRepo
}

Now as this class has only a single constructor Spring will use this to do dependency injection. This is called constructor based dependency injection.

@Service
@Transactional
public class StudentService {
    @Autowire
    private StudentRepository studentRepo;
    // complete service code using studentRepo
}

Whereas this is called field based dependency injection.

IMHO you should prefer constructor based dependency injection for the simple reason it is very easy to use and right in your face. You can easily test it while with field injection writing a unit test is hard(er) as you need reflection to inject the field.

See also Dependency Injection in Java for a more thorough explanation of different dependency injection styles.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
2

Dependency injection can be achieved in different ways. The two ways that you're talking about and probably not understand clearly are:

  1. Field Injection:
@Service
public class StudentService {
  @Autowired
  private StudentRepository studentRepo;
   // complete service code using studentRepo
}
  1. Constructor Based DI:
@Service
//@AllArgsConstructor <-- commenting this for now. Probably your source of confusion
@Transactional
public class StudentService {
    private final StudentRepository studentRepo;

     // For Spring Boot 1.4 and above, using @Autowired on constructor is optional
     // Dependency being injected through constructor
    public StudentService(StudentRepository studentRepo) {
             this.studentRepo = studentRepo;
    }
     // complete service code using studentRepo
}

Now, if you put @AllArgsConstructor (an annotation from project lombok), the constructor would be generated with all the member fields for you in the .class file and required DI would take place.

adarsh
  • 1,393
  • 1
  • 8
  • 16