이 글은 강의 : 김영한님의 - "스프링 핵심원리 - 기본편"을 듣고 정리한 내용입니다. 😁😁
옵션 처리와 생성자 주입에 대해서 공부해보자.
@Autowired를 사용했지만 주입할 스프링 빈이 없어도 동작해야할 때가 있다.
자동 주입할 대상이 없을 때, @Autowired만 사용하면 오류가 발생한다. (기본적으로 required = true이기 때문!)
package hello.core.autowired;
public class AutowiredTest {
@Test
void AutoWiredOption() {
// TestBean 스프링 빈 등록
ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
}
static class TestBean {
// 자동으로 주입할 대상이 없으면 오류 발생
@Autowired // required=true
public void setNoBean1(Member noBean1) {
// Member 는 스프링 빈이 아님
System.out.println("noBean1 = " + noBean1);
}
}
자동 주입할 대상이 없을 때도 로직을 실행시키고 싶을 때 사용하는 방법
@Autowired(required=false)
@Nullable
Optional<> 등이 있음.
과거에는 수정자 주입, 필드 주입을 많이 사용했지만, 최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다. 생성자 주입을 사용해야하는 이유를 아래에서 차례로 설명한다.
생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 불변하게 설계할 수 있다.
생성자 주입을 사용하면 주입할 데이터를 누락했을 때, **컴파일 오류**가 발생한다. IDE에서 바로 어떤 값을 필수로 주입해야 하는지 알 수 있다.
생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있다. 그래서 생성자에서 값이 초기화되지 않는 오류를 컴파일 시점에 막아준다.
@Component
public class OrderServiceImpl implements OrderService{
// 생성자 주입을 쓰면 final 키워드를 사용해 생성자에서 초기화 누락을 방지, 불변하도록 설계O
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
// 생성자 주입
@Autowired // 생성자가 1개일 때 @Autowired 생략O
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
//this.discountPolicy = discountPolicy;
}
...
}
(참고) 수정자 주입을 포함한 나머지 주입 방식은 모두 생성자 이후에 호출되므로, 필드에 final 키워드를 사용할 수 없다. 오직 생성자 주입 방식만 final 키워드를 사용할 수 있다.
정리하면, 생성자 주입 방식은 프레임워크에 의존하지 않고 순수한 자바 언어의 특징을 잘 살리는 방법이다.
- 기본으로 생성자 주입을 사용하고 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여한다. 필드 주입은 사용X