본문 바로가기

공부 정리/Java

@Qualifier & @Resource & @Autowired

728x90
반응형

문득, 인터페이스를 구현한 클래스들의 @Component등록을 보면서 @Qualfier와 @Resrouce를 살펴보게 되었다.

 

@Autowired로 객체를 사용하고 싶을 때, Spring Container에 Type이 같은 객체들이 여러개 등록되어있다면, 어떤 것을 사용할지 명시해주어야 한다.

public interface Party {

}

====

package com.sourceallies.person;
...
@Component
public class Person implements Party {

}

===

package com.sourceallies.organization;
...
@Component
public class Organization implements Party {

}

public example {
 @Autowired
 private Party party; //오류! 어떤 Bean을 사용할 것인가 명시해주어야 한다!
}

 

그때 @Autowired와 함께 @Qualifier를 사용하고, @Resource는 @Autowired와 @Qualifier를 한번에 간결하게 표현할 수 있다. 이런 차이 이외에도 상속, 구현 중복 경우에 Bean을 주입하기 위해 거치는 절차의 미묘한 차이를 살펴본다.

 

1. @Autowired와 @Resource의 주입 순서 차이

 

@Autowired and @Inject

  1. Matches by Type
  2. Restricts by Qualifiers
  3. Matches by Name

@Resource

  1. Matches by Name
  2. Matches by Type
  3. Restricts by Qualifiers (ignored if match is found by name)

 

interface Party와 이를 구현하는 Person , Organization 클래스를 살펴보자.

 

@Component뒤에 이름이 없으면 클래스 이름으로 Bean이 등록된다는 것을 기억한다. 각각 Person과 Organization 클래스는 각각 person, organization으로 등록될 것이다.

 

혹시 person 대신에 내가 원하는 이름으로 등록시켜 주고 싶다면 @Component("beanName")을 사용한다. 이제 Bean을 주입하기 위해서는 partyperson이라는 name을 꼭 명시해야한다.

@Component("partyperson")
public class Person implements Party {

}

 

* field name에 주입

@Resource
private Party person;
// Type : Party, Name : person

@Autowired
private Party person;
// Type : Party, Name : person

@Inject
private Party person;
// Type : Party, Name : person

@Resource는 Name을 먼저 확인한다. 따라서 person을 검색한다. person 이 Spring Container에 등록되어 있으므로 주입이 된다.

 

@Autowired와 @Inject는 Type를 먼저 확인한다. 따라서, Party와 관련된 Bean은 person, organization이므로 어떤 것을 주입해야하는지 모르기 때문에 Qualifier를 확인한다. 없으므로 마지막에 Name을 확인한다.

 

* field Type에 주입

@Resource
private Person party;
// Type : Person, Name : party

@Autowired
private Person party;
// Type : Person, Name : party

@Inject
private Person party;
// Type : Person, Name : party

@Resource는 처음에 Name을 확인하지만, 명확히 알 수 없어 Type인 Person을 보고 person을 주입한다.

 

@Autowired, @Inject는 Type인 Person을 보고 person을 바로 주입한다.

 

 

* @Qualifier 사용

 

명시적으로 @Qualifier를 사용해서 Bean을 주입해본다.

@Resource
@Qualifier("bad")
private Party person;

@Autowired
@Qualifier("bad")
private Party person;

@Inject
@Qualifier("bad")
private Party person;

@Resrouce는 Name에 부합하는 Bean을 찾으면, @Qaulifier를 무시한다. 따라서 person이 주입된다.

 

@Autowired와 @Inject는 Type인 Party로 식별하지 못한다. 따라서 @Qualifier로 식별하려고 하지만, "bad"라는 것은 존재하지 않기 때문에  ‘NoSuchBeanDefinitionException’ 예외를 발생하며 종료된다.

 

@Resource는 혹여나 @Component("bad") class Person이,가장 기본적인 class Person로 Bean의 이름이 바뀐다고 한들, name을 가장 먼저 확인하기 때문에, @Autowired와 @Inejct와는 달리 안전장치를 하나 더 가질 수 있다. 리팩토링과정에서, 혹은 언제나 변경 가능한 가능성을 염두해두고 코딩을 해야 하므로, 간결하면서도 안전장치를 하나라도 더 가지고 있는 @Reousource사용은 어떨까? 물론, 항상 @Reousrce 사용이 언제나 안전한 장치 1개를 더 가지는 것은 아니지만 말이다.

 

* 차이점

Annotation Package Source
Resource javax.annotation Java
Qualifier javax.inject Java
Inject javax.inject Java
Autowired org.springframework.bean.factory Spring

 

@Resource는 JSR-250 규칙을 따른다. 따라서 Spring 뿐만 아니라 다른 FrameWork에서 DI로 사용할 수 있다.

@Resource는 간결하게 표현할 수 있는 장점이 있다.

@Autowired 스프링에 종속한 기술이다. @Inject는 @Autowired와 같은 역할을 하지만 JSR-299로 Java의 규칙이다.

 

 

728x90
반응형

'공부 정리 > Java' 카테고리의 다른 글

Filter vs Interceptor 차이 (Spring)  (0) 2021.08.13
Validation 어노테이션 직접 만들어보기  (0) 2021.08.12
AOP  (0) 2021.08.11
Spring MVC  (0) 2021.08.08
IoC, DI  (0) 2021.08.08