의존관계 주입방법 4가지
- 생성자 주입
- Setter 주입(수정자 주입)
- 필드 주입
- 메서드 주입
대부분의 경우 생성자 주입을 사용하며, 특별한 경우에 setter 주입을 사용한다.
1. 생성자 주입
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
//final을 선언해서 값이 없거나, 값이 변하면 오류
@Autowired // 생성자가 1개이므로 @Autowired생략해도 자동 주입됨
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
- 생성자를 통해서 의존 관계를 주입 받는 방법
불변 / 필수
의존관계에 사용 → 의도치 않게 변경할 가능성을 낮춰줌(원인 파악이 힘든 버그의 원인)- 생성자 호출 시점에 딱 1번만 호출되는것이 보장된다
→ 빈 등록시에 생성자가 실행이 되기 때문
2. Setter 주입(수정자 주입)
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
// setter생성자 주입
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
// setter생성자 주입
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
- setter라 불리는 수정자 메서드를 통해서 의존관계 주입
선택 / 변경
가능성이 있는 의존관계에 사용- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법
- 사용자가 생성된 객체를 직접
set~
메서드를 호출해서 주입
→ 스프링 컨테이너가 빈을 등록한 후에 의존관계 주입된다. public
을 사용함으로 인해 의존성 주입에 선택/변경이 가능하지만, 불변성이 보장되지 않는다.@Autowired
가 없으면 의존 관계 주입X →@Autowired
생략 불가능!
3. 필드 주입
@Component
public class OrderServiceImpl implements OrderService {
//필드 의존관계 주입
@Autowired private MemberRepository memberRepository;
@Autowired private DiscountPolicy discountPolicy;
}
- 필드에 바로 주입하는 방식
- 외부에서 변경이 불가능해서 테스트하기가 힘들다.
→ 실제 코드에 사용하기에는 적합하지 않음 - 일반적으로 권장하지 않음
- 서로 객체를 참조하는
순환 참조
의 경우 문제가 발생
→생성자 주입
은 먼저 빈을 찾고 없으면 생성 하기때문에 문제가 발생하지 않는다.
4. 일반 메서드 주입
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
//일반 메서드 주입
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
- 일반 메서드를 사용해서 의존관계 주입
- 실제 사용할 일은 잘 없다.
옵션 처리
- 주입할 스프링 빈이 없어도 동작해야 하는 경우 옵션처리를 한다.
3가지 처리 방법
@Autowired(required = false)
: 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출이 안됨@Nullable
: 자동 주입할 대상이 없으면 null로 출력, 메서드는 실행됨Optional<>
: 자동 주입할 대상이 없으면 Optional.empty가 입력됨(객체를 Optional로 감싼 형태)/
요약 - 생성자 주입을 사용할 것!
불변
- 의존관계의 대부분은 생성자 의존관계 주입을 사용한다.
→ 의존관계의 대부분은 애플리케이션 종료시점까지 의존관계 변경할 일이 없기 때문 setter의존 관계
를 사용하는 경우public
으로 설정해야함.
→ 누군가가 실수로 수정할 수도 있고, 불변성이 필요한 속성을 열어두는 것은 좋은 설계가 아님
누락
- setter의존 관계시에 주입 데이터를 누락했을 경우 NPE(Null Point Exception)이 발생한다.
- 생성자 의존관계 +
final 필드
를 사용하면, 자바빈이 생성 되면서 주입이 같이 되기때문에 이러한 오류가 예방됨 - 생성자 주입은 프레임워크에 의존하지 않고, 자바 언어의 특징을 잘 살리는 방법
반응형