객체 간의 관계, 즉 의존관계는 @Autowired
를 통해 설정한다.
이러한 의존관계 주입의 방법은 네 가지가 있다.
당연한 것이나, Spring Bean이 아닌 곳에서는 @Autowired
코드가 아무 기능도 제공하지 않는다.
Spring을 포함한 대부분의 framework는 생성자 주입을 권장한다.
이유는 다음과 같다.
불변이 보장된다.
대부분의 의존관계는 한 번 설정된 이후로 프로그램 종료 시점까지 변경할 일이 없다.
따라서 Setter 주입 혹은 메서드 주입 등을 사용하면 외부에서 실수로 변경할 수 있으므로, 변경할 수 없도록생성자 주입을 권장한다.
데이터 누락 시 compile error를 발생시킨다.
Setter 주입의 경우, 의존관계 주입을 누락했을 시 실행 이후에야 NullPointException
이 발생한다.
그러나 생성자 주입의 경우, 컴파일 오류가 발생함으로써 IDE를 통해 오류를 빠르게 감지할 수 있다. 이를 통해 final 키워드를 사용할 수 있게된다.
이외에도 명시성, 테스트 용이성, 순환 의존성 방지 등 여러 장점을 지니고있다.
따라서 항상 생성자 주입을 택하되 옵션이 필요한 경우에 Setter 주입을 동시에 사용하자.
기본적으로 @Autowired
는 주입할 Bean이 없으면 동작하지 않는다.
만일 Bean이 없어도 동작하게끔 하려면, 다음과 같은 세 가지 방법이 있다.
@Autowired(required=false)
: 주입할 대상이 없으면 해당 메서드가 호출되지 않는다.
@Nuallble
: 주입할 대상이 없으면null
이 입력된다.
Optional<>
: 주입할 대상이 없으면Optional.empty
가 입력된다.
위 세 메서드에 대한 실행 결과이다.
@Autowired
은 기본적으로 타입을 이용해 동작한다.
즉, ac.getBean(TypeName.class);
등의 코드처럼 동작한다.
따라서, 해당 타입의 구현체가 2개 이상일 경우 NoUniqueBeanDefinitionException
에러가 발생한다.
하위 타입으로 조회할 수도 있지만, 이는 DIP를 위배함과 동시에 유연성이 저하된다.
이를 해결하기 위한 방법인 다음 세 가지에 대해 하나씩 알아보자.
@Autowired
필드명@Qualifier
@Primary
@Autowired
는 처음으로 타입 매칭을 시도한다.
이때 매칭되는 Bean이 여러 개인 경우, 필드명과 매칭되는 Bean을 찾는다.
위와같이
DiscountPolicy
에 대한 Bean이 두 개 이상일 경우, 아래 코드는 오류를 발생시킨다.
이때, 아래와같이 필드명
discountPolicy
를 rateDiscountPolicy
로 변경하면, 매칭되는 Bean인 RateDiscountPolicy
로 의존관계가 주입된다.
@Qualifier
는 의존관계 주입시 추가 구분자를 붙이는 방법이다.
Bean 등록시 @Qualifier
를 붙여주자.
이후, 의존관계 주입시에도
@Qualifier
와 구분자 이름을 붙여주면 된다.
@Primary
는 Bean의 우선순위를 정하는 방법이다.
RateDiscountPolicy
가 FixDiscountPolicy
보다 우선순위를 가지도록 하자.
좋은 정보 감사합니다.❤️❤️