Spring은 @Autowired 어노테이션을 이용한 다양한 의존성 주입(DI; Dependency Injection) 방법을 제공합니다.
의존성 주입은 필요한 객체를 직접 생성하는 것이 아닌 외부로부터 객체를 받아 사용하는 것입니다.
이를 통해 객체간의 결합도를 줄이고 코드의 재활용성을 높일 수 있습니다.
@Autowired 는 Spring에게 의존성을 주입하는 지시자 역할로 쓰입니다.
의존성 주입은 위의 3가지 방법이 있습니다. 그렇다면 어떤 주입 방법을 사용하는게 가장 좋을까요?
우선, 의존성 주입 방법을 하나씩 알아보도록 하겠습니다.
@Controllerpublic class CocoController {
//final을 붙일 수 있음
private final CocoService cocoService;
@Autowired
public CocoController(CocoService cocoService) {
this.cocoService = cocoService; }}
클래스의 생성자가 하나이고, 그 생성자로 주입받을 객체가 빈으로 등록되어 있다면 @Autowired를 생략 할 수 있습니다.
@Controllerpublic class CocoController {
@Autowired
private CocoService cocoService;}
필드에 @Autowired 어노테이션만 붙여주면 자동으로 의존성 주입됩니다.
사용법이 매우 간단하기 때문에 가장 많이 접할 수 있는 방법입니다.
단점
코드가 간결하지만, 외부에서 변경하기 힘들다.
프레임워크에 의존적이고 객체지향적으로 좋지 않다.
@Controllerpublic class CocoController {
private CocoService cocoService;
@Autowired
public void setCocoService(CocoService cocoService) {
this.cocoService = cocoService; }}
Setter 메소드에 @Autowired 어노테이션을 붙이는 방법입니다.
수정자 주입을 사용하면 setXXX 메서드를 public으로 열어두어야 하기 때문에 언제 어디서든 변경이 가능하다.
Spring Framwork reference에서 권장하는 방법은 생성자를 통한 주입입니다.
@Autowired 어노테이션만으로 간단하게 의존성을 주입할 수 있는데 왜 생성자 주입 방법을 권장하는걸까요?
필드 주입이나 수정자 주입과 다르게 생성자 주입 방법이 주는 장점에 대해 알아보도록 하겠습니다.
@Servicepublic class AService {
// 순환 참조
@Autowired
private BService bService;
public void HelloA() {
bService.HelloB(); }}
@Servicepublic class BService {
// 순환 참조
@Autowired
private AService aService;
public void HelloB() {
aService.HelloA(); }}
필드 주입과 수정자 주입은 빈이 생성된 후에 참조를 하기 때문에 어플리케이션이 아무런 오류 그리고 경고 없이 구동됩니다.
그리고 그것은 실제 코드가 호출될 때까지 문제를 알 수 없다는 것입니다.
반면, 생성자를 통해 주입하고 실행하면 BeanCurrentlyInCreationException이 발생하게 됩니다.
순환 참조 뿐만아니라 더 나아가서 의존 관계에 내용을 외부로 노출 시킴으로써 어플리케이션을 실행하는 시점에서 오류를 체크할 수 있습니다.
@Controllerpublic class CocoController {
private final CocoService cocoService;
public CocoController(CocoService cocoService) {
this.cocoService = cocoService;
}}
출처: https://dev-coco.tistory.com/70 [슬기로운 개발생활:티스토리]