스프링 의존성 주입 방법
필드 주입
▶ 필드 주입
- 필드에 @Autowired를 붙여서 주입하는 방법
▶ 필드 주입 특징
- 코드가 간결하다.
- 외부에서 변경이 힘들다.
- 프레임워크에 의존적이다.
- 정상적으로 작동되려면 setter가 필요하다.
- 필드 주입은 DI 컨테이너 안에서 작동하여 자바 코드로 테스트하기 어렵다.
@Controller
public class ProductController {
@Autowired
private ProductService productService;
}
생성자 주입
▶ 생성자 주입
- 생성자를 통해 의존 관계를 주입받는 방법
- 생성자에 @Autowired를 하면 @Component로 등록된 빈에서 생성자에 필요한 빈 주입
▶ 생성자 주입 특징
- 클래스의 생성자가 하나이고, 생성자로 주입받을 객체가 빈으로 등록돼있으면 @Autowired 생략가능.
- 불변과 필수 의존 관계에 사용
- NullPointerException 방지 가능
- 주입 받을 필드를 final 선언 가능
@Controller
public class ProductController {
private final ProductService productService;
@Autowired //생략가능
public ProductController(ProductService productService) {
this.productService = productService;
}
}
Setter 주입
▶ Setter 주입
- 필드의 값을 변경하는 수정자 메서드로 의존 관계를 주입하는 방법
- @Component를 통해 클래스를 스프링 빈으로 등록하고 @Autowired가 있는 수정자들을 의존관계 주입
▶ Setter 주입 특징
- setter 주입을 사용하면 set메서드의 접근제한자가 public이기 때문에 변경이 쉽다.
- 선택과 변경 가능성이 있는 의존관계 사용
@Controller
public class ProductController {
private ProductService productService;
@Autowired
public void setProductService(ProductService productService) {
this.productService = productService;
}
}
🔥 생성자 주입을 사용하는 이유
1) 불변성
- 생성자로 의존성 주입 시 final 선언이 가능해 런타임에서 의존성 주입을 받는 객체의 변동이 없어지게 된다.
그리고 final로 선언한 생성자 주입 방식은 null이 불가능한 장점이 있다.
2) 순환 참조 방지
- 필드 주입과 수정자 주입은 빈이 생성도니 후에 참조하여 아무런 오류 없이 구동이 되며, 실제 해당 코드가 호출될 때까지 알 수 없는 문제가 있다. 하지만 생성자를 통해 주입하고 실행 시 에러가 발생하고 의존 관계를 외부로 노출시켜 애플리케이션 실행 시점에서 알 수 있다.
3) 테스트 용이
- 테스트 코드를 좀 더 편리하게 작성할 수 있고, POJO를 사용하면 DI 컨테이너 없이도 의존성 주입하여 사용가능 하다.
이러한 점을 통해 코드 가독성이 높아지며, 유지보수가 용이하고 테스트의 격리성과 예측 가능성을 높일 수 있다.
참고
https://ittrue.tistory.com/227
https://dev-coco.tistory.com/70