빈을 주입하는 방법에는 다양한 방법이 있다.
생성자 주입, 수정자 주입, 필드 주입이 있지만 요즘은 대부분 생성자 주입을 추구하는 상황이다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MemberServiceImpl implements MemberService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
위와 같이 수정자 주입을 사용한 코드가 있을 때 set 메서드를 통해서 마음대로 의존 관계를 바꿀 수 있지만 생성자 주입을 사용하면 그 일을 방지할 수 있다.
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class MemberServiceImplTest {
@Test
void createMember() {
MemberServiceImpl memberService = new MemberServiceImpl(new MemorymemberRepository(), new FixDiscountPolicy());
}
}
수정자 주입을 사용하면 항상 set 메서드를 통해서 값을 지정해줘야 하지만 생성자 주입을 사용하면 그럴 필요가 없다.
만약 생성자 인수에 값이 들어가야 한다면 new 키워드를 사용해서 더미 객체를 만들어서 집어 넣어주면 된다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public MemberServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
// 실수로 여기에 discountPolicy를 정해주지 않았을 때 IDE나 컴파일러 차원에서 오류 해결 가능
}
}
개발자가 실수로 생성자에 필드 값을 지정해주지 않았을 때, final 키워드를 사용하면 그 일을 컴파일러 차원에서 방지할 수 있다.
final 키워드는 생성자 주입일 때만 사용 가능한 키워드이다.