🔎 목차
- 자동 의존 관계 주입
- 생성자 주입
- 수정자 주입
- 필드 주입
- 일반 메서드 주입
📌 자동 의존관계 주입
@Component를 통해 스프링 빈을 등록하면 의존 관계 주입을 직접 해줄 수 없으므로 자동 의존관계 주입을 해주어야 한다.
자동 의존관계 주입 방법 4가지
1. 생성자 주입
- 생성자를 통해 의존관계 주입한다.
- 생성자 위에
@Autowired를 추가한다.
- 컴포넌트 스캔을 통해 스프링 빈 등록될 때 생성자 호출하면서 의존관계가 주입된다.
- 본래 스프링 컨테이너 생성 과정
- 스프링 빈 등록
- 의존관계 주입
- 생성자를 통한 자동 생성자 주입의 경우 스프링 컨테이서 생성 과정
- 스프링 빈 등록과 동시에 의존관계 주입
2. 수정자 주입
- setter를 통해 의존관계 주입한다.
- 관례상 setter명을
set필드명으로 한다.
3. 필드 주입
- 필드에 바로 주입한다.
- 필드에 바로
@Autowired를 추가한다.
4. 일반 메서드 주입
- 일반 메서드를 통해 주입한다.
- 메서드 위
@Autowired를 추가한다.
🍃 생성자 주입
생성자 주입
- 생성자를 통해 의존관계 주입한다.
- 만약 생성자가 1개라면
@Autowired 생략이 가능하다.
특징
- final 키워드를 사용할 수 있다.
- 생성자 호출 시점에 의존관계 주입된다. -> 딱 한번만 호출된다.
- 빈 생성과 동시에 의존관계 주입이 일어난다.
- 스프링 컨테이너는 빈 생성 -> 의존관계 주입으로 두 단계가 나뉘지만 생성자 주입의 경우 동시에 일어남
- 값 세팅 후 변경이 불가능하다.
코드 예시
@Component
public class MemoryMyRepository implements MyRepository {
private final MyBean myBean;
@Autowired
public MemoryMyRepository(MyBean myBean){
this.myBean = myBean;
}
}
🍃 수정자 주입
수정자 주입 - setter
- setter를 통해 의존관계 주입한다.
- setter 위에
@Autowired 추가
- 변경의 가능성이 있음
- 보통
set메서드명으로 이름을 짓는다.
특징
- setter는 public으로 열어둔다. -> 변경의 가능성이 있다.
- 의존관계 주입 단계 때 주입이 일어난다.
- 생성자와 수정자 모두 있어도 수정자 호출한다.
- 스프링이 싱글톤을 보장하므로 같은 인스턴스 호출된다.
코드 예제
@Component
public class MemoryMyRepository implements MyRepository {
private MyBean myBean;
@Autowired
public void setMyBean(MyBean myBean) {
this.myBean = myBean;
}
}
참고! @Autowired 는 주입할 대상이 없으면 오류 발생한다. 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false) 를 활용하면 된다.
🍃 필드 주입
필드 주입
- 선언 필드에 바로 주입한다.
- final 키워드 사용이 불가능하다.
특징
- 코드가 매우 간결해진다.
- DI 프레임워크에 의존적이다.
- 외부에서 변경 불가능하다.
- 순수한 자바 코드 테스트에서 NullPointerException 에러 발생한다.
- DI 프레임워크가 의존관계 주입해주어야 하는데 순수한 자바 코드에는 없기 때문!
- 생성자를 통해 의존관계 주입하여 테스트를 진행하면 된다. -> 생성자 추가 코드 발생
- 간단한 테스트에서만 쓰는 것을 추천 (DI 프레임워크 환경)
코드 예제
@Component
public class MemoryMyRepository implements MyRepository {
@Autowired private MyBean myBean;
}
🍃 일반 메서드 주입
메서드 주입
- 의존관계 주입하려는 메서드를 직접 만들 수 있다.
특징
- 한번에 여러 필드 주입 가능하다.ㅣ
- 잘 사용하지 않는다.
- 일반 메서드 코드를 추가하기보다 생성자, 수정자를 통한 의존관계 주입이 더 깔끔하다.
@Component
public class MemoryMyRepository implements MyRepository {
private MyBean myBean;
@Autowired
public void init(MyBean myBean){
this.myBean = myBean;
}
}
추가로 어떤 방법으로 의존관계 주입을 하면 좋을까?
스프링을 포함한 DI 프레임워크 대부분은 생성자 주입을 권장한다! 그 이유는 다음과 같다.
불변
- 대부분 의존관계는 애플리케이션 종료 시점전까지 변하면 안 된다.
- 대부분 의존관계 주입 후 변경하는 일은 거의 없다.
- 수정자 주입, 일반 메서드 주입의 경우 메서드를 public으로 열어야 한다. 이는 수정의 위험성이 있다.
누락
- 필요한 의존관계를 누락없이 진행할 수 있다.
- 생성자 주입의 경우 필요한 의존관계를 바로 알 수 있다.
- 혹여나 빠트릴 경우 컴파일 에러로 바로 알 수 있다.
- 수정자 주업의 경우 널포인트 에러가 발생할 수 있다. 이는 어떤 의존관계가 필요한지 한번에 알기 쉽지 않다.
final 키워드
- final
- 생성하면 바뀌지 않는다. -> 불변
- final을 사용한 필드는 초기화를 해주거나 생성자를 통해 값을 넣어야 한다.
- 값이 설정되지 않는다면 컴파일 에러가 발생한다. -> 누락방지
- final 키워드를 사용할 경우 불변과 누락을 동시에 지킬 수 있다.
출처
인프런 '스프링 핵심 원리 - 기본편' 강의