생성자 주입
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
대부분의 의존 관계는 애플리케이션 종료 전까지 변경할 일이 없다.
setter 주입을 사용하려면 메서드를 public으로 열어두어야 한다.
(이는 좋은 설계 방법이 아니다)
필요한 의존 관계가 누락되었을 때, 컴파일 오류로 쉽게 고칠 수 있다.
필드에 final 키워드를 사용할 수 있다.
(생성자에서 값이 설정되지 않는 오류를 컴파일 시점에 막아준다)
생성자를 사용함으로써 프레임워크에 의존하지 않고, 순수 자바 언어의 특징을 잘 살리는 방법이기도 하다.
기본으로 생성자 주입을 사용하고, 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여하면 된다. (동시에 사용 가능)
수정자 주입(setter 주입)
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
필드 주입 - 사용 X
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
일반 메서드 주입 - 사용 X
@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;
}
}
@Component
@RequiredArgsConstructor // final가 붙은 필드를 모아서 생성자를 자동으로 생성
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
@Autowired를 생략하는 방법을 주로 사용@RequiredArgsConstructor 함께 사용하여 깔끔한 코드를 제공@Autowired는 타입으로 조회하기 때문에 선택된 빈이 2개 이상일 때 문제가 발생한다.NoUniqueBeanDefinitionException 오류가 발생한다.@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
// DiscountPolicy는 FixDiscountPolicy, RateDiscountPolicy를 하위 타입으로 가진다.
// 어떤 것을 생성자에 넣어줘야 할지 모르기 때문에 예외 발생한다.
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
DiscountPolicy discountPolicy) { // 이 부분에서 예외 발생
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Component
public class FixDiscountPolicy implements DiscountPolicy {}
@Component
public class RateDiscountPolicy implements DiscountPolicy {}
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository,
DiscountPolicy rateDiscountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = rateDiscountPolicy; // RateDiscountPolicy 의존성 주입
}
@Autowired