IoC 컨테이너 3부 - @Autowire
참고문헌
IoC 컨테이너 3부: @Autowire
- 필요한 의존 객체의 “타입"에 해당하는 빈을 찾아 주입한다.
@Autowired
- required: 기본값은 true (따라서 못 찾으면 애플리케이션 구동 실패)
사용할 수 있는 위치
- 생성자 (스프링 4.3 부터는 생략 가능)
- 세터
- 필드
결론
- 같은 타입의 여러 클래스의 빈을 등록하는 경우, 주입하고자 하는 클래스에 @Primary를 사용하는 것을 추천한다.
경우의 수
- 해당 타입의 빈이 없는 경우
- 애플리케이션 구동 실패
- setter 주입을 사용하는 경우에도 @Autowired를 사용하면 해당 빈을 컨테이너에서 찾기를 시도하고, 없으면 애플리케이션 구동이 실패한다 (required = True가 기본값이므로)
- 따라서 이럴땐 required = false로 설정하면, bookRepository 인스턴스를 생성해서 setter로 주입하는 방식으로 애플리케이션을 구동할 수 있다.
- 필드 주입의 경우에도 마찬가지로 required=false로 설정하므로써 BookRepository가 빈으로 등록되어 있지 않더라도 주입해서 애플리케이션을 구동할 수 있다.
-
해당 타입의 빈이 한 개인 경우
- 해당 타입의 빈이 여러 개인 경우
- 빈 이름으로 시도,
- 같은 이름의 빈 찾으면 해당 빈 사용 : 필드변수명을 빈으로 생성되는 클래스 이름(카멜케이스)와 동일하게 주면, 해당 빈을 찾음
- 같은 이름 못 찾으면 실패
- 다음 목차
- 빈 이름으로 시도,
같은 타입의 빈이 여러개 일 때 (필드변수명과 같은 유일한 빈을 찾지 못한 경우)
- 케이스 : BookRepository를 인터페이스로, 그 구현체가 2개가 있으며 빈으로 등록되어 있을 때, 서비스에서 BookRepository를 Autowire해서 주입받고자 한다면, 둘 중 어떤 것을 골라야 할 지 모르기 때문에 에러가 발생
-
스프링에서는 3가지 해결책을 제시한다.
- @Primary
- 이 어노테이션이 붙은 빈을 가져온다
- 스프링 러너 구현해서 아래와 같이 테스트해볼 수 있다.
-
해당 타입의 빈 모두 주입 받기
-
@Qualifier (빈 이름으로 주입)
- @Primary와는 다르게, 주입을 하는, @Autowired가 사용되는 부분에서 어떤 것을 사용할 지 명시하는 방식
- 빈은 클래스명을 카멜케이스로 해서 자동생성되는데, 이 클래스명을 명시해줘서 사용함
- 문자열 입력으로 type safety하지 않아서, @Primary가 주로 사용됨
동작 원리
- 첫시간에 잠깐 언급했던 빈 라이프사이클 기억하세요?
-
BeanPostProcessor
- 새로 만든 빈 인스턴스를 수정할 수 있는 라이프 사이클 인터페이스
- @Primary, @Autowired 등 라이프 사이클 로직을, 다른 빈들에게 적용하는 역할
- AutowiredAnnotationBeanPostProcessor extends BeanPostProcessor
- 스프링이 제공하는 @Autowired와 @Value 애노테이션 그리고 JSR-330의 @Inject 애노테이션을 지원하는 애노테이션 처리기.
- ApplicationContext (빈 컨테이너)에 자동으로 빈으로 등록되어 있음