computer_study

[Spring] 04. 의존 자동 주입 본문

스터디/스프링5 프로그래밍 입문

[Spring] 04. 의존 자동 주입

knowable 2022. 4. 9. 22:57

목차

1. 예제 프로젝트 준비

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

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

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

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

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

1. 예제 프로젝트 준비

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

자동 주입 기능을 사용하면, 의존 객체를 명시하지 않아도 스프링이 필요한 의존 빈 객체를 찾아와서 주입한다.

(@Autowired 애노테이션을 필드나 세터 메서드에 붙이면 타입이 일치하는 빈 객체를 찾아 주입한다.)

//////////// @Autowired 없을 때 AppCtx.java ///////////////

@Configuration
public class AppCtx{
    @Bean
    public MemberDao memberDao(){
        return new MemberDao();
    }
    
    @Bean
    public ChanbePasswordService changePwdSvc(){
        ChangePasswordService pwdSvc = new ChangePasswordService();
        pwdSvc.setMemberDao(memberDao());
        return pwdSvc;
    }
}

//////////// @Autowired 사용 시 AppCtx.java ///////////////
@Configuration
public class AppCtx{
    @Bean
    public MemberDao memberDao(){
        return new MemberDao();
    }
    
    @Bean
    public ChangePasswordService changePwdSvc(){
        ChangePasswordService pwdSvc = new ChangePasswordService();
        return pwdSvc;
    }
}
//////////// @Autowired 사용 시 ChangePasswordService.java ///////////////
public class ChangePasswordService{
    @Autowired
    private MemberDao member Dao;
    
    public void setMemberDDao(MemberDao memberDao){
        this.memberDao = memberDao;
    }
    
    // ... //
}

 

일치하는 빈이 없는 경우

  • No qualifying bean of type '찾으려는bean' available 에러 메시지

일치하는 빈이 두 개 이상인 경우

  • expected single matching bean but found 2 에러 메시지

친절하게 메시지로 다 알려준다.

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

자동 주입이 가능한 빈이 두 개 이상을 때, 주입할 빈을 지정할 수 있는 애노테이션

/////// AppCtx.java ////
@Configuration
public class AppCtx{
    @Bean
    @Qualifier("printer")
    public MemberPrinter memberPrinter1(){
        return new MemberPrinter();
    }
    
    @Bean
    public MemberPrinter memberPrinter2(){
        return new MemberPrinter();
    }
}

/////// MemberListPrinter.java ////
public class MemberListPrinter{
    @Autowired
    @Qualifier("printer")
    public void setMemberPrinter(MemberPrinter printer){
        this.printer = printer;
    }

}

@Qualifier 애노테이션 값으로 printer를 준 MemberPrinter 타입의 빈(memberPrinter1)을 자동 주입 대상으로 사용

 

@Qualifier를 사용하지 않는다면 필드나 파라미터 이름을 기본적으로 한정자로 사용한다.

@Bean
public MemberPrinter printer(){
    return new MemberPrinter();
}

위와 같은 경우는 한정자로 필드 이름인 "printer"를 사용한다.

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

클래스 A가 있고 클래스 A2는 A를 상속한다고 가정

public class A2 extends A{

   ....

}

///// AppCtx.java ////
@Configuration
public clas AppCtx{
   @Bean
   public A number1(){
       return new A();
   }
   
   @Bean
   public A2 number2(){
       return new A2();
   }
}

///// tmp.java ///
public class tmp{
    private A temp;

    @Autowired
    public void setTmp(A temp){
        this.temp = temp;
    }

}

이런 경우, A2클래스는 A타입에도 할당할 수 있으므로 스프링 컨테이너는 A 타입 빈을 자동 주입하는 @Autowired 애노테이션을 만나면 A, A2 중 어떤 빈을 주입해야되는지 알 수 없다.

 

해결방법

  • @Qualifier 애노테이션을 사용해서 주입 할 대상 지정
  • tmp.java에 setTmp(A temp)가 아닌 setTmp(A2 temp) 로 지정해주면, A2타입의 빈은 하나만 존재하므로 문제를 해결할 수 있다.

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

  • required 속성으로 지정 가능
    • 필수가 아니라면 지정
    • 필드가 존재하지 않으면 익셉션 없이 자동 주입을 수행하지 않는다
    • @Autowired(required = false)
  • Optional을 사용
    • 일치하는 값이 없다면 Optional을 인자로 전달하기에 익셉션이 발생하지 않는다
    • 일치하는 값이 있다면 해당 빈을 갖는 Optional을 인자로 전달
    • ex)private DateTimeFormatter dateTimeFormatter;
           public void setDateFormatter(Optional<DateTimeFormatter> formatterOpt)
  • @Nullable 애노테이션 사용
    • 존재하지 않으면 인자로 null을 전달한다
    • request속성을 false로 지정 할 때와 차이점
      • @Nullable은 자동 주입할 빈이 존재하지 않아도 메서드를 호출
      • required가 false라면 새터 메스드를 호출하지 않는다.

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

설정 클래스에서 세터 메서드를 통해 의존을 주입해도 해당 헤터 메서드에 @Autowired 애노테이션이 붙어 있으면 자동 주입을 통해 일치하는 빈을 주입한다.

 

자동 주입과 수동 주입 코드가 섞여있으면 NullPointerException 발생 시 원인 찾기가 힘들다.

웬만하면 일관되게 사용하는 것이 좋다.

 

 

 

Comments