1. Constructor Injection(생성자 주입)
@Component
public class MadExample {
// final로 선언할 수 있는 보너스
private final HelloService helloService;
// 단일 생성자인 경우는 추가적인 어노테이션이 필요 없다.
public MadExample(HelloService helloService) {
this.helloService = helloService;
}
}
2. Field Injection(필드 주입)
@Component
public class MadExample {
@Autowired
private HelloService helloService;
}
3. Setter Injection(수정자 주입)
@Component
public class MadExample {
private HelloService helloService;
@Autowired
public void setHelloService(HelloService helloService) {
this.helloService = helloService;
}
}
Spring에서는 1. 생성자 주입 방법을 더 권장하는 이유가 뭘까?
실행 결과에 차이가 발생하는 이유가 뭘까?
빈을 주입하는 순서
가 다르다.Setter Injection(수정자 주입)은 우선 주입 받으려는 빈의 생성자를 호출하여 빈을 찾거나 빈 팩터리에 등록한다. 그 후에 생성자 인자에 사용하는 빈을 찾거나 만든다. 그리고 주입하려는 빈 객체의 수정자를 호출하여 주입한다.
Field Injection(필드 주입)은 수정자 주입 방법과 동일하게 먼저 빈을 생성한 후에 어노테이션이 붙은 필드에 해당하는 빈을 찾아서 주입하는 방법이다.
마지막으로 Constructor Injection(생성자 주입)
은 생성자로 객체를 생성하는 시점에 필요한 빈을 주입한다. -> 먼저 빈을 생성하지 않는다.
그렇기 때문에 순환 참조는 생성자 주입에서만 문제가 된다. 객체 생성 시점에 빈을 주입하기 때문에 서로 참조하는 객체가 생성되지 않은 상태에서 그 빈을 참조하기 때문에 오류가 발생한다.
그렇다면 순환 참조 오류를 피하기 위해서 수정자 또는 필드 주입을 사용해야 할까? 오히려 그렇지 않다. 순환 참조가 있는 객체 설계는 잘못된 설계이기 때문에 오히려 생성자 주입을 사용하여 순환 참조되는 설계를 사전에 막아야 한다.
https://madplay.github.io/post/why-constructor-injection-is-better-than-field-injection