#4 Spring 의존성 주입 방법
1. @Autowired
@Autowired 어노테이션을 사용하지 않을 때의 의존성 주입
<!-- XML 설정파일 --> <!-- 생성자를 통한 의존성 주입 --> <bean id="itemRepository" class="com.example.SampleProject.service.ItemService"> <constructor-arg ref="itemRepository"/> </bean> <!-- Setter를 통한 의존성 주입 --> <bean id="itemRepository" class="com.example.Sample.service.ItemService"> <property name="itemRepository" ref="itemRepository"/> </bean>
XML 파일에 bean을 주입받을 클래스를
태그를 사용하여 등록 bean을 주입받을 클래스는 생성자와 Setter중 어느쪽을 통해 주입받을지 선택
@Autowired 사용시 의존성 주입
- 의존성을 주입받아야할 부분에 @Autowired 어노테이션 사용
- Spring은 bean 컨테이너에서 매칭되는 타입의 bean을 찾아 자동으로 의존성을 주입
@Qualifier
- 같은 타입의 bean이 복수 존재할 경우 어느것을 주입받을지 명시하기 위한 어노테이션
- @Autowired와 함께 @Qualifier('<bean이름>') 을 붙여주면 해당 bean을 주입받을 수 있음
- 같은 타입의 bean이 여러개일 때 Qualifier를 설정하지 않으면 에러가 발생
- 해당 타입의 bean이 유일하게 존재하더라도 Qualifier와 매칭되지 않으면 주입받을 수 없음
2. 세 가지 주입 방식(@Autowired 사용 기준)
생성자를 통한 주입
package com.example.SampleProject.service; public class ItemService { private final ItemRepository itemRepository; @Autowired public ItemService(ItemRepository itemRepository) { this.itemRepository = itemRepository; } }
의존성을 주입받을 필드를 선언
bean을 인자로 받아 필드를 초기화하는 생성자를 정의
생성자에 @Autowired 를 사용
생성자가 하나뿐일 경우 @Autowired는 생략 가능
초기화 과정을 거치기 때문에 의존성을 주입받을 필드를 final로 선언할 수 있음
생성 이후에 다른 의존성을 주입하는 것은 불가능
Setter를 통한 주입
package com.example.SampleProject.service; public class ItemService { private ItemRepository itemRepository; @Autowired public setItemService(ItemRepository itemRepository) { this.itemRepository = itemRepository; } }
생성자 주입과 유사한 구조이나 생성자 대신 Setter를 사용
생성과 동시에 초기화되는 것이 아니기 때문에 final 사용 불가
생성 이후에도 Setter를 사용하여 다른 의존성 주입 가능
필드에 직접 주입
package com.example.SampleProject.service; public class ItemService { @Autowired private ItemRepository itemRepository; }
필드에 직접 @Autowired를 붙여줘도 의존성 주입 가능
생성과 동시에 초기화되는 것이 아니기 때문에 final 사용 불가
필드 주입을 지원하는 프레임워크의 존재에 의존적
외부에서 필드에 접근 불가
Spring에서는 생성자를 통한 주입을 사용할 것을 권장
생성자 주입을 사용해야하는 이유?
Compile Time에서의 순환 참조 검출
필드 주입, Setter주입의 경우 객체 생성시에 바로 의존성을 주입하지 않음
=> 순환 참조가 발생하는 클래스에 의존하더라도 compile time에서는 에러가 발생하지 않음생성자 주입의 경우 객체 생성 시점에서 의존성을 주입
=> 객체가 생성되는 순간 순환 참조 에러가 검출, compile time에 에러를 발견할 수 있음
Immutable한 객체 보장 가능
생성자 주입에서는 final을 사용하여 주입받은 객체가 불변임을 보장할 수 있음
생성시에 주입받은 객체가 변경되어야 하는 경우는 극히 드물기 때문에 유용
편리한 테스트코드 작성
- 필드 주입과 달리 생성자는 생성시에 한해 프레임워크의 도움 없이 직접 의존성 주입 가능
- 테스트용 Mock 클래스를 사용하여 생성자를 호출하는 것으로 간단하게 테스트 코드 작성 가능
3. @Resource
Java 표준이 지원하는 의존성 주입용 어노테이션
@Autowired 와 달리 Spring 프레임워크를 사용하지 않아도 사용 가능
Bean 탐색 순서의 차이
@Autowired
Type이 일치하는 Bean을 먼저 탐색
없을 경우 에러 발생
Type이 일치하는 Bean이 하나라면 바로 주입
Type이 일치하는 Bean이 복수 존재할 경우 id로 구분
id가 매칭되는 Bean이 하나라면 바로 주입
id로도 하나의 Bean을 특정할 수 없을 경우 에러 발생
@Qualifier를 통해 id를 지정 가능
@Resource
- @Autowired와 유사하나 Type과 id의 우선순위가 역전
- 어노테이션의 name 속성(attribute)값으로 id 지정 가능