
@Resource 어노테이션과 @Autowired 어노테이션의 차이
두 어노테이션 모두 의존성을 주입하는 어노테이션이다.
해당 어노테이션을 사용하여 IoC 컨테이너에 등록된 빈 객체를 자동으로 주입한다.
어떤 차이가 있는지 보자
@Autowired
-
필드, 메서드, 생성자에 사용할 수 있다.
-
Bean의 타입을 사용해서 주입할 빈 객체를 찾는다.
-
하나의 인터페이스는 한 개의 클래스로만 구현할 수 있다. (두 개 이상의 클래스가 구현하면 안 된다.)
마지막 특징 때문에 @Resource 어노테이션을 사용한다. (@Qualifier 또는 @Primary 어노테이션을 사용해도 된다.)
아래의 예제를 살펴보자
public interface A {}
@Component
public class B implements A {}
@Component
public class C implements A {}
위와 같은 경우 A를 구현하는 클래스 B, C 모두가 @Component 어노테이션을 사용해 스프링 빈 객체로 등록되어 있는 상태이다. 이후 다른 Service 클래스에서 의존성 주입을 받는다고 가정한다.
@Service
public class HelloService {
@Autowired
private A a;
}
이러한 경우 주입받는 구현체가 B 클래스인지, C 클래스인지 알 수 없다.
@Autowired 어노테이션 사용 시 빈 객체를 찾는 순서는 다음과 같다.
-
타입이 같은 빈 객체를 찾는다.
-
만약 타입이 같은 빈 객체가 두 개 이상이고, @Qualifier 어노테이션이 붙어있지 않은 경우 이름이 같은 빈 객체를 찾는다.
-
@Qualifier(또는 @Primary) 어노테이션이 붙어있다면 해당 어노테이션으로 지정된 빈 객체를 찾는다.
@Resource
-
필드, 메서드에 사용할 수 있다. 생성자에는 사용할 수 없다.
-
Bean의 이름을 사용해서 주입할 빈 객체를 찾는다.
사용 시 아래와 같은 형태로 사용한다.
@Resource(name = "memberRepository")
private MemberRepository memberRepository;
이처럼 name 값을 지정하여 사용하기 때문에 한 개의 인터페이스를 여러 개의 클래스가 구현해도 상관없다.
@Resource 어노테이션 사용 시 빈 객체를 찾는 순서는 다음과 같다.
-
name 속성 값으로 지정한 빈 객체를 찾는다.
-
name 속성이 존재하지 않는다면 동일한 타입을 갖는 빈 객체를 찾는다.
-
name 속성이 존재하지 않고, 동일한 타입을 갖는 빈 객체가 두 개 이상인 경우-앞서 A, B, C로 예시를 든 경우- 이름이 같은 빈 객체를 찾는다.
-
name 속성이 존재하지 않고, 동일한 타입을 갖는 빈 객체가 두 개 이상이고, 이름이 같은 빈 객체마저도 없는 경우에는 @Qualifier 어노테이션(또는 @Primary)을 사용해서 주입할 빈 객체를 찾아야 한다.
추가로 @Primary, @Qualifier를 살펴보자
public interface A {}
@Component
public class B implements A {}
@Component @Primary
public class C implements A {}
같은 타입의 Bean 객체가 여러 개 존재할 때 @Primary 어노테이션이 붙은 클래스가 있다면 해당 빈 객체를 주입한다.
@Component
@Qulifier("b")
public class B implements A {}
@Component
@Qulifier("c")
public class C implements A {}
@Service
public class HelloService {
@Autowired @Qulifier("b")
private A a;
}
qualifier value가 b로 설정된 클래스는 B 클래스임을 뜻한다. 따라서 위 예시에서는 필드 이름을 a로 하더라도 B 클래스로 구현된 빈 객체가 주입될 것이다.