Spring @Autowired 의존관계 주입

김두현·2023년 5월 20일
2

Spring

목록 보기
9/13
post-thumbnail

의존관계 주입 방법

객체 간의 관계, 즉 의존관계는 @Autowired를 통해 설정한다.
이러한 의존관계 주입의 방법은 네 가지가 있다.

  • ❗️생성자 주입 : 생성자가 하나일 경우 생략 가능하다.
  • Setter 주입
  • 필드 주입
  • 일반 메서드 주입

당연한 것이나, Spring Bean이 아닌 곳에서는 @Autowired 코드가 아무 기능도 제공하지 않는다.


생성자 주입을 사용하자.

Spring을 포함한 대부분의 framework는 생성자 주입을 권장한다.
이유는 다음과 같다.

불변이 보장된다.

대부분의 의존관계는 한 번 설정된 이후로 프로그램 종료 시점까지 변경할 일이 없다.
따라서 Setter 주입 혹은 메서드 주입 등을 사용하면 외부에서 실수로 변경할 수 있으므로, 변경할 수 없도록생성자 주입을 권장한다.

데이터 누락 시 compile error를 발생시킨다.

Setter 주입의 경우, 의존관계 주입을 누락했을 시 실행 이후에야 NullPointException이 발생한다.
그러나 생성자 주입의 경우, 컴파일 오류가 발생함으로써 IDE를 통해 오류를 빠르게 감지할 수 있다. 이를 통해 final 키워드를 사용할 수 있게된다.

이외에도 명시성, 테스트 용이성, 순환 의존성 방지 등 여러 장점을 지니고있다.

따라서 항상 생성자 주입을 택하되 옵션이 필요한 경우에 Setter 주입을 동시에 사용하자.


주입 대상 처리

기본적으로 @Autowired는 주입할 Bean이 없으면 동작하지 않는다.
만일 Bean이 없어도 동작하게끔 하려면, 다음과 같은 세 가지 방법이 있다.

  1. @Autowired(required=false) : 주입할 대상이 없으면 해당 메서드가 호출되지 않는다.

  1. @Nuallble : 주입할 대상이 없으면 null이 입력된다.

  1. Optional<> : 주입할 대상이 없으면 Optional.empty가 입력된다.

위 세 메서드에 대한 실행 결과이다.


@Autowired 조회 오류

@Autowired은 기본적으로 타입을 이용해 동작한다.
즉, ac.getBean(TypeName.class); 등의 코드처럼 동작한다.
따라서, 해당 타입의 구현체가 2개 이상일 경우 NoUniqueBeanDefinitionException 에러가 발생한다.

하위 타입으로 조회할 수도 있지만, 이는 DIP를 위배함과 동시에 유연성이 저하된다.

이를 해결하기 위한 방법인 다음 세 가지에 대해 하나씩 알아보자.

  1. @Autowired 필드명
  2. @Qualifier
  3. @Primary

@Autowired 필드명

@Autowired는 처음으로 타입 매칭을 시도한다.
이때 매칭되는 Bean이 여러 개인 경우, 필드명과 매칭되는 Bean을 찾는다.

위와같이 DiscountPolicy에 대한 Bean이 두 개 이상일 경우, 아래 코드는 오류를 발생시킨다.
이때, 아래와같이 필드명 discountPolicyrateDiscountPolicy로 변경하면, 매칭되는 Bean인 RateDiscountPolicy로 의존관계가 주입된다.


@Qualifier

@Qualifier는 의존관계 주입시 추가 구분자를 붙이는 방법이다.

Bean 등록시 @Qualifier를 붙여주자.
이후, 의존관계 주입시에도 @Qualifier와 구분자 이름을 붙여주면 된다.


@Primary

@Primary는 Bean의 우선순위를 정하는 방법이다.

RateDiscountPolicyFixDiscountPolicy보다 우선순위를 가지도록 하자.


참고 자료

https://www.inflearn.com/course/스프링-핵심-원리-기본편


💕오류 지적 및 피드백은 언제든 환영입니다. 복제시 출처 남겨주세요!💕
💕좋아요와 댓글은 큰 힘이 됩니다.💕
profile
I AM WHO I AM

2개의 댓글

comment-user-thumbnail
2023년 5월 21일

좋은 정보 감사합니다.❤️❤️

1개의 답글