@Autowired
이 어노테이션을 필드나 setter 메서드에 사용하면 Spring은 타입이 같은 Bean을 찾아 자동으로 해당 필드나 매개변수에 주입한다.
만약 해당 어노테이션을 적용한 대상과 타입이 일치하는 Bean이 없거나, 타입이 일치하는 Bean이 2개 이상인 경우 익셉션이 발생한다.
@Autowired 사용 예시
@Autowired 어노테이션을 사용하면 설정 클래스의 Bean 설정 메서드에서 의존 객체를 따로 주입할 필요가 없다. 이를 통해 Bean 설정 메서드의 코드를 더욱 간결하게 작성할 수 있다.
@Qualifier("Bean 한정값")
이 어노테이션이 사용된 필드/파라미터와 타입이 같으면서 지정된 한정값을 갖는 Bean을 찾아 주입한다. 이 어노테이션을 적용한 대상이 @Bean 설정 메서드라면 해당 Bean의 한정값을 지정한 값으로 설정하고,@Autowired가 사용된 필드/메서드라면@Qualifier어노테이션에서 지정한 값과 한정값이 같은 Bean을 찾아서 할당한다.@Qualifier()
만약 이 어노테이션으로 한정값을 별도로 지정하지 않았다면 필드나 @Bean 설정 메서드의 이름을 기본 한정값으로 사용한다.
@Autowired를 적용한 대상과 타입이 같은 Bean이 여러 개라면 필드/파라미터와 타입이 동일한 Bean 중 어느 것을 자동 주입 대상으로 선택해야 하는지 분명하지 않기 때문에 UnsatisfiedDependencyException이 발생한다. 이러한 상황에서는 해당 타입의 Bean을 주입받는 모든 @Autowired 어노테이션에 대해 @Qualifier를 적용하여 자동 주입 대상인 Bean을 정확히 지정해야 의존 자동 주입이 정상적으로 수행될 수 있다.
/* MemberPrinter는 MemberSummaryPrinter의 상위 타입,
MemberSummaryPrinter 타입은 MemberPrinter 타입 필드/파라미터에 할당 가능 */
public class MemberSummaryPrinter extends MemberPrinter {
@Override
public void print(Member member) {
System.out.printf("회원 정보: 이메일=%s, 이름=%s\n", member.getEmail(), member.getName());
}
}
/* 아래의 코드는 @Autowired로 주입할 수 있는 Bean이 여러 개일 때와 같은 Exception 발생*/
@Configuration
public class AppCtx {
... 생략
/* 상속 관계에 있는 상위 타입과 하위 타입을 모두 Bean으로 설정한 상황 */
@Bean
public MemberPrinter memberPrinter() { // 상위 타입
return new MemberPrinter();
}
@Bean
public MemberSummaryPrinter memberPrinter2() { // 하위 타입
return new MemberSummaryPrinter();
}
... 생략
}
서로 상속관계인 상위 타입과 하위 타입의 Bean을 설정하고 @Qualifier를 적용하지 않은 경우, 같은 타입의 Bean이 여러 개인 상황에서 @Autowired를 사용하여 해당 타입의 Bean을 주입할 때와 동일한 Exception이 발생한다.
이러한 Exception은 하위 타입 클래스와 상위 타입 클래스 간 상속관계로 인해 발생한다. 즉, 클래스 간 상속 관계로 인해 하위 타입의 Bean 또한 상위 타입 Bean에 할당할 수 있으므로 결국 동일한 타입의 Bean이 여러 개 있는 상황에서 해당 타입에 관해 @Autowired를 적용하여 의존 자동 주입을 수행했을 때와 동일한 익셉션을 유발한다.
따라서 상위 타입 Bean과 하위 타입 Bean을 모두 사용하는 상황에서 의존 자동 주입을 수행할 경우, 상황에 맞게 다음의 추가 조치를 취하는 것이 좋다.
@Qualifier어노테이션 적용하기@Autowired가 적용된 필드/메서드가 하위 타입 Bean을 자동 주입받도록 타입을 변경하기
@Autowired를 적용한 타입에 해당하는 Bean이 없다면 기본적으로 Exception이 발생한다. 하지만@Autowired를 통해 자동 주입할 대상이 필수가 아니라면 다음의 방법들을 필드/파라미터에 적용하여 의존 자동 주입을 선택적으로 수행할 수 있다.
@Autowired(required = false) 어노테이션
매칭되는 Bean이 없다면 자동 주입 대상인 필드/파라미터로의 값 전달 자체를 수행하지 않아 기존 값이 갱신되지 않는다.
메서드에 사용했을 경우 파라미터와 매칭되는 Bean이 없다면 해당 메서드는 실행되지 않는다.Optional 타입 사용(자바 8 버전 이후)
자동 주입 대상의 타입으로 지정하는 방식으로 사용한다. 만약 매칭되는 Bean이 존재하지 않으면 값이 없는Optional을, 존재하면 해당 Bean을 값으로 갖는Optional을 전달한다.@Nullable 어노테이션
자동 주입 대상이 되는 필드/메서드에 매칭되는 Bean이 있다면 해당 Bean을, 없다면 null을 전달하므로 기존에 할당된 값이 갱신될 수 있다.
메서드의 파라미터에 이 어노테이션을 사용한 경우,@Autowired(required = false)어노테이션을 사용했을 떄와는 달리 자동 주입할 Bean이 존재하지 않아도 메서드를 호출할 수 있다.
- 자동 주입 :
@Autowired어노테이션을 사용한 의존 주입- 명시적 의존 주입(수동 주입) : 생성자나 setter 메서드의 파라미터로 의존 대상을 직접 전달
Spring 설정 클래스에서 자동 주입 대상에 관해 명시적 의존 주입을 수행했더라도, Spring 해당 필드/메서드에 @Autowired 어노테이션이 사용된 경우 의존 자동 주입을 우선적으로 수행한다. 또한 자동 주입을 수행하는 코드와 수동 주입을 수행하는 코드가 섞여 있을 경우, NullPointException이 발생했을 때 그 원인을 찾는 것이 어려워질 수도 있다.
따라서 @Autowired 어노테이션을 통한 자동 주입을 사용한다면 자동 주입을 적용하기 어려운 경우가 아닌 이상 자동 주입을 일관적으로 사용하는 것이 좋다.