자동 주입: 스프링이 자동으로 의존하는 빈 객체를 주입해주는 것
자동 주입을 사용하려면 @Autowired 애노테이션 혹은 @Resource 애노테이션을 사용하면 된다.
자동 주입 기능을 사용하려면 의존을 주입할 대상에 @Autowired 애노테이션을 붙이기만 하면 된다.
@Autowired 애노테이션을 붙이면 설정 클래스에서 의존을 주입하지 않아도 된다. 스프링이 알아서 해당 타입의 빈 객체를 찾아서 필드에 할당한다.
찾아보니 이를 다른 말로 필드 주입이라고도 부르는 것 같다.
@Autowired를 사용할 때, 필드에 적절한 빈이 주입하지 않으면 NullPointerException이 발생할 수 있다. 따라서 가능하면 생성자 주입을 사용하자.
@Autowired 애노테이션은 메서드에도 붙일 수 있다. 빈 객체의 메서드에 @Autowired를 붙이면 스프링은 해당 메서드를 호출하며 메서드 파라미터 타입에 해당하는 빈 객체를 찾아 인자로 주입한다.
@Autowired를 사용할 때 해당 타입의 빈이 없으면 적용할 수 없는 빈이 있다는 에러 메시지가 출력된다. 반대로 같은 타입의 빈이 여러개 있다면 해당 타입의 빈을 한정할 수 없다는 에러 메시지가 출력된다. @Autowired를 사용하려면 해당 타입을 가진 빈이 어떤 빈인지 정확하게 한정할 수 있어야 한다.
위에서 본 것처럼 자동 주입 가능한 빈이 여러개일 경우 어떤 빈을 주입할 지 지정할 수 있는 방법이 필요하다.
이 때 사용되는 것이 @Qualifier 애노테이션이다.
@Qualifier 애노테이션을 사용할 수 있는 위치
사용 예시
@Autowired
@Qualifier("printer")
public void setMemberPrinter(MemberPrinter printer) {
this.printer = printer;
}
이렇게 하면 한정값이 "printer"인 빈을 의존 주입 후보로 사용한다.
한정자가 없는 경우 기본적으로 빈의 이름이나 파라미터 이름을 한정자로 사용한다.
MemberPrinter라는 클래스와 이를 상속하는 MemberSummaryPrinter라는 클래스가 있다고 가정해보자. MemberPrinter 타입의 빈과 MemberPrinter 타입의 빈을 @Qualifier 없이 자동 주입 한다면 정상적으로 작동할까?
아니다. 앞에서 동일한 타입의 빈이 여러 개 있으면 빈을 한정할 수 없다는 에러 메시지가 출력된다고 했는데, 이 경우에도 동일한 에러가 발생할 것이다. 왜냐하면 MemberSummaryPrinter 클래스를 MemberPrinter에도 할당할 수 있기 때문이다.
이를 해결하기 위해서는 @Qualifier 애노테이션을 적절히 활용하거나, MemberSummaryPrinter로 자동 주입하여야 한다. 이 경우에 MemberSummaryPrinter 타입의 빈은 하나밖에 없기 때문이다.
기본적으로 @Autowired 애노테이션은 해당 애노테이션을 붙인 타입에 해당하는 빈이 존재하지 않으면 익셉션을 발생시킨다. 하지만 빈이 반드시 존재할 필요가 없는 경우도 있을 수 있다. 이런 경우에는 어떻게 해야할까?
@Autowired 애노테이션에는 required 라는 속성이 있다. 이 required 속성값을 false로 해주면 매칭되는 빈이 없어도 익셉션이 발생하지 않는다.
@Autowired(required = false)
또는 자바 8 이상의 버전에서는 Optional을 인자로 전달하는 방법도 있다.
@Autowired
public void setDateFormatter(Optional<DateTimeFormatter> formatterOpt) {
// do something
}
이 외에도 @Nullable 애노테이션을 사용하는 방법도 있다.
@Autowired
public void setDateFormatter(@Nullable DateTimeFormatter dateTimeFormatter) {
// do something
}
@Nullable과 required=false의 차이
required=false의 경우 주입 대상 빈이 없는 경우 아예 세터메서드를 호출하지 않지만, Nullable의 경우 주입 대상 빈이 존재하지 않으면 세터메서드를 호출하고 null 값을 전달한다.
설정 클래스에서 의존을 주입했는데 자동 주입 대상인 경우 자동 주입이 우선시된다.
자동 주입과 수동 주입을 섞어 사용하면 주입이 제대로 되지 않아 NullPointerException 이 발생할 수 있으니 일관된 주입 방식을 사용하도록 하자.