책읽기

[스프링5 프로그래밍 입문][chap04] 의존 자동 주입

pythaac 2022. 3. 8. 20:15

1. 예제 프로젝트

  • 의존 자동 주입
    • 의존 대상을 설정코드에서 직접 주입하지 않고, 스프링이 자동으로 객체를 주입하는 기능
  • 의존 주입 관련 애노테이션
    • @Autowired
    • @Resource : 자바에서 제공하는 애노테이션

 

2. @Autowired 애노테이션을 이용한 의존 자동 주입

  • @Autowired
    • 의존을 주입할 대상에 붙이는 애노테이션
    • 필드나 세터 메서드에 붙이면 스프링은 타입이 일치하는 빈 객체를 찾아서 주입
    • 설정 파일에서 사용하기 위해 기본 생성자가 필요
@Bean
public MemberDao memberDao() {
    return new MemberDao();
}
  • 세터 메서드의 자동 주입 구현 과정
    • 기본 생성자를 추가
    • 세터 메서드에 @Autowired 추가
    • 설정 파일에서 기본 생성자로 return
  • 일치하는 Bean이 없는 경우
    • 타입이 일차히는 Bean이 없으면 Exception
    • 타입이 일치하는 Bean이 2개 이상이면 Exception

 

3. @Qualifier 애노테이션을 이용한 의존 객체 선택

  • @Qualifier
    • 자동 주입 가능한 빈이 2개 이상일 때 지정하는 방법
// 설정 파일 내에서 등록된 빈
@Bean
@Qualifier("printer")
public MemberPrinter memberPrinter1() {
    return new MemberPrinter();
}

// 자동 주입하는 세터 메서드
@Autowired
@Qualifier("printer")
public void setMemberPrinter(MemberPrinter printer){
    this.printer = printer;
}
  • 빈 이름과 기본 한정자
빈 이름 @Qualifier 한정자
printer   printer
printer2 mprinter mprinter

 

4. 상위/하위 타입 관계와 자동 주입

  • 빈 등록과 상속 관련
  • 시나리오
    • MemberPrinter라는 객체가 빈으로 등록
    • MemberPrinter가 자동 주입의 대상
    • MemberPrinter를 상속받는 객체 MemberSummaryPrinter를 생성하여 빈으로 등록
    • [에러] MemberSummaryPrinter가 MemberPrinter를 상속받아 MemberPrinter 타입으로 할당 가능
@Bean
public MemberPrinter memberPrinter1() {
    return new MemberPrinter();
}

@Bean
public MemberSummaryPrinter memberPrinter2() {
    return new MemberSummaryPrinter();
}
  • 해결방안
    • 1) @Qualifier 애노테이션 활용
    • 2) 자식 클래스 타입을 주입
    • [의문] 자식 클래스 타입을 주입해도 여전히 MemberPrinter 타입 객체는 자동 주입이 불가능하지 않는가?
@Autowired
public void setMemberPrinter(MemberSummaryPrinter printer){
    this.printer = printer;
}

 

5. @Autowired 애노테이션의 필수 여부

  • @Autowired 애노테이션의 동작 관련
  •  시나리오
    • dataTimeFormatter가 null이어도 동작하도록 구현함
    • @Bean으로 등록되지 않은 dataTimeFormatter에 @Autowired
    • [결과] Exception 발생 : 등록된 빈이 없기 때문
    • [문제] null이어도 동작하도록 구현하였는데 Exception이 발생함
  • 해결방안
    • 1) required 속성
      주입 의존이 null이면 메서드가 호출되지 않음
    • 2) 자바 8의 Optional
      주입 의존이 null인지 isPresent() 메서드로 확인 가능
    • 3) @Nullable
      주입 의존이 null이면 null을 주입
// 1) required 속성
@Autowired(require = false)

// 2) 자바 8의 Optional
@Autowired
public void setDataFormatter(Optional<DataTimeFormatter> formatterOpt) {
    if (formatterOpt.isPresnet()){
        this.dataTimeFormatter = formatterOpt.get();
    } else {
        this.dataTimeFormatter = null;
    }
}

// 3) @Nullable
@Autowired
public void setDataFormatter(@Nullable DataTimeFormatter dataTimeFormatter) {
    this.dataTimeFormatter = dataTimeFormatter;
}
  • 생성자 초기화와 필수 여부 지정 방식 동작 이해
    • 시나리오
      • 생성자에서 dataTimeFormatter를 생성하여 저장 (초기화)
      • 세터 메서드에 자동 주입 설정 (빈으로 등록되지 않음)
      • 정상 동작
        • 1) required 속성을 이용
          dataTimeFormatter가 초기화한 객체로 사용됨 (메서드가 호출되지 않음)
        • 2) @Nullable을 이용
          dataTimeFormatter가 null로 주입되어 null로 처리 (메서드가 호출됨)
    • [의문] 1) required 속성과 2) @Nullable의 차이를 유용하게 사용할 수 있는 상황은 어떤 상황이 있을까?

 

6. 자동 주입과 명시적 의존 주입 간의 관계

  • 자동 주입이 최종
    • 설정 클래스에서 세터 메서드를 통해 의존을 주입하는 상황
    • 해당 세터 메서드에 @Autowired 애노테이션이 붙어 있으면 자동 주입이 최종 실행