0. 출처
아직 배우고 있는 중이라 부정확한 정보가 포함되어 있을 수 있습니다!
주의하세요!
올인원 스프링 프레임워크 참고.
1. 문제 발생
![Featured image for [Spring] 의존 객체 자동 주입_1](https://tired-i.com/wp-content/uploads/2026/01/spring-1-image-9.png)
앞서 의존 객체 자동 주입_1에서 의존 객체를 자동으로 주입해 보았다.
앞선 글에 사용한 예제는 아주 단순하기 때문에 아무런 문제 없이 의존 객체를 자동으로 주입할 수 있었다.
하지만 조금만 코드가 복잡해지면 의존 객체가 자동으로 주입되지 않을 수 있다.
예를 들어 만약 생성자가 여러 개 오버로딩되어 있다면 어떨까?
가. 수동 주입
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService">
<constructor-arg ref="contactDao"/>
</bean>
Code language: HTML, XML (xml)
의존 객체를 자동으로 주입하기 이전에는 <constructor-arg>를 가지고서 어떤 생성자를 사용할지 판단할 수 있었다.
나. 자동 주입
하지만 자동으로 주입하는 경우는 조금 다르다.
지난 시간에 사용한 예제를 보자.
package ch05_pjt_01.contact.service;
import ch05_pjt_01.contact.ContactSet;
import ch05_pjt_01.contact.dao.ContactDao;
public class ContactRegisterService {
private ContactDao contactDao;
public ContactRegisterService(ContactDao contactDao) {
this.contactDao = contactDao;
}
public void register(ContactSet contactSet) {
String name = contactSet.getName();
if(verify(name)){
contactDao.insert(contactSet);
}else {
System.out.println("The name has already regiseterd.");
}
}
public boolean verify(String name){
ContactSet contactSet = contactDao.select(name);
return contactSet == null ? true : false;
}
public void SetWordDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
}
Code language: JavaScript (javascript)
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService"/>
Code language: JavaScript (javascript)
registerService bean은 의존 객체를 자동으로 주입하게 되면서 <constructor-arg ref="contactDao"/>를 생략했다.
만약 이 상태에서 또 다른 생성자를 추가하면 어떻게 될까?
public ContactRegisterService(){}
Code language: CSS (css)
이제 어떤 생성자를 사용해서 의존객체를 생성할지 판단할 수 없게 된다.
이런 문제를 해결하기 위해서 @Autowired, @Resource, @Inject를 사용한다.
2. @Autowired
가. 생성자에 연결
import org.springframework.beans.factory.annotation.Autowired;
...
public ContactRegisterService(){}
@Autowired
public ContactRegisterService(ContactDao contactDao){
this.contactDao = contactDao;
}
Code language: JavaScript (javascript)
@Autowired는 실행에 필요한 객체를 데이터 타입을 바탕으로 스스로 추측하여 주입한다.
즉, ContactRegisterService 객체가 생성될 때 필요한 ContactDao 객체를 데이터 타입을 바탕으로 판단하여 주입한다.
@Autowired는 생성자 외에도 필드와 메서드에도 사용할 수 있다.
나. 필드에 연결
import org.springframework.beans.factory.annotation.Autowired;
...
@Autowired
private ContactDao contactDao;
public ContactRegisterService(){}
//@Autowired
//public ContactRegisterService(ContactDao contactDao){
// this.contactDao = contactDao;
//}
Code language: PHP (php)
디폴트 생성자에 의해서 ContactRegisterService가 생성되고 @Autowired한 contactDao는 자동 주입된다.
직관적이기 때문에 가장 많이 사용된다.
다. 메서드, setter에 연결
import org.springframework.beans.factory.annotation.Autowired;
...
//@Autowired
//private ContactDao contactDao;
//public ContactRegisterService(){}
//@Autowired
//public ContactRegisterService(ContactDao contactDao){
// this.contactDao = contactDao;
//}
@Autowired
public void setContactDao(ContactDao contactDao){
this.contactDao = contactDao;
}
Code language: JavaScript (javascript)
라. 주의점
@Autowired필드 또는 메서드에 적용할 때는 반드시 디폴트 생성자가 필요한다.@Autowired는 객체 생성에 필요한 객체를 데이터 타입을 바탕으로 스스로 추측하여 주입한다. 이때 같은 데이터 타입을 가진 bean이 여러 개 있는 경우 문제가 된다. 즉,ContactRegisterService객체가 생성될 때 필요한ContactDao객체를 데이터 타입을 바탕으로 판단하는데ContactDao타입을 사용하는contactDao1,contactDao2가 있을 경우 둘 중 어느 것을 주입할 지 판단할 수 없다. (해결법은 아래에)
3. @Resource
@Resource도 @Autowired와 비슷하다.
@Resource를 사용해서 의존 객체를 자동으로 주입받을 수 있다.
이때 다른 점은 다음과 같다.
| @Autowired | @Resource | |
| 의존 객체 탐색 방법 | 데이터 타입 바탕 | 빈 객체의 이름 |
| 적용 대상 | 생성자, 필드, 메서드 | 필드, 메서드 |
| annotation 제공 | spring | java |
@Autowired와 다르게 빈 객체의 이름을 바탕으로 객체를 탐색해서 주입한다.
또한 생성자에 연결할 수 없고 오직 필드와 메서드에만 사용할 수 있다.
spring이 아닌 java에서 제공하는 annotation임으로 spring을 사용하지 않는 java 프로젝트에서도 사용할 수 있다.
단, spring에서 @Resouce를 사용하려면 pom.xml에 빌드 설정을 추가해야 한다.
<!-- pom.xml에 추가-->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotaion-api</artifactId>
<version>1.3.2</version>
</dependency>
Code language: HTML, XML (xml)
가. 필드에 연결
import javax.annotation.Resource;
@Resouce
private ContactDao contactDao;
Code language: CSS (css)
appCtx.xml에서 contactDao라는 이름을 가진 bean을 주입한다.
나. 메서드에 연결
import javax.annotation.Resource;
private ContactDao contactDao;
@Resource
public void setContactDao(ContactDao contactDao){
this.contactDao = contactDao;
}
Code language: JavaScript (javascript)
다. 주의점
- 생성자에 연결할 순 없다.
@Resource는 스프링이 아닌 자바 자체의 annotation이다. → Maven 설정 파일 pom.xml에 설정을 추가해야 함.
4. @Qualifier
ContactDao 타입을 사용하는 bean이 여러 개 있다고 가정해 봅시다.
<bean id="contactDao1" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao3" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService" />
Code language: JavaScript (javascript)
@Autowired와 @Resource 모두 @Qualifier를 사용해서 주입할 bean을 명시적으로 지정할 수 있다.
이를 통해서 @Autowired와 @Resource가 가진 문제를 해결할 수 있다.
가. @Autowired의 경우
@Autowired는 객체 생성에 필요한 객체를 데이터 타입을 바탕으로 스스로 추측하여 주입한다.
이때 같은 데이터 타입을 가진 bean이 여러 개 있는 경우 문제가 된다.
즉, ContactRegisterService 객체가 생성될 때 필요한 ContactDao 객체를 데이터 타입을 바탕으로 판단하는데 ContactDao 타입을 사용하는 contactDao1, contactDao2, contactDao3가 있을 경우 어느 것을 주입할지 판단할 수 없다.
이때 @Qualifier를 사용해서 주입할 bean을 명시적으로 지정할 수 있다.
이를 통해서 @Autowired가 가진 문제를 해결할 수 있다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@Autowired
@Qualifier("usedDao")
private ContactDao contactDao;
Code language: CSS (css)
ContactDao 데이터 타입을 사용하면서 Qualifier가 usedDao인 것을 골라서 주입한다.
<bean id="contactDao1" class="ch05_pjt_01.contact.dao.ContactDao" >
<qualifier value="usedDao"/>
<bean/>
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao3" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService" />
Code language: JavaScript (javascript)
contactDao1가 qualifier가 usedDao기 때문에 주입된다.
나. @Resource의 경우
@Resource는 bean의 이름을 바탕으로 객체를 탐색해서 주입한다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@Resource
private ContactDao contactDao;
Code language: CSS (css)
contactDao1, contactDao2, contactDao3은 있지만 contactDao라는 이름의 bean이 없다.
그래서 주입할 객체를 찾을 수 없는 문제가 있다.
이때 @Resource도 @Qualifier를 사용해서 주입할 bean을 명시적으로 지정할 수 있다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@Resource
@Qualifier("usedDao")
private ContactDao contactDao;
Code language: CSS (css)
<bean id="contactDao1" class="ch05_pjt_01.contact.dao.ContactDao" >
<qualifier value="usedDao"/>
<bean/>
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao3" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="registerService" class="ch05_pjt_01.contact.service.ContactRegisterService" />
Code language: JavaScript (javascript)
이를 통해서 @Autowired와 @Resource가 가진 문제를 해결할 수 있다.
다. @Qualifier를 생략 가능한 경우
bean id와 같은 이름을 사용하는 경우 @Qualifier를 생략할 수 있다.
<bean id="contactDao" class="ch05_pjt_01.contact.dao.ContactDao" /> // 수정
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao3" class="ch05_pjt_01.contact.dao.ContactDao" />
Code language: JavaScript (javascript)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@Resource 또는 @Autowired
//@Qualifier("usedDao") 생략 가능
private ContactDao contactDao;
Code language: CSS (css)
라. 매개변수 개수가 2개 이상인 경우
public class Example{
@Autowired
public Example(@Qualifier("hello") FirstBean fBean, @Qualifier("world") SecondBean sBean) { ... }
Code language: PHP (php)
5. @Inject
@Autowired와 기능적으로 유사하지만, @Inject도 @Resource처럼 Java의 javax.inject 패키지에서 제공하는 애노테이션이다.
기능적으로 유사하다는 것은 생성자, 필드, 메서드에 사용할 수 있고 데이터 타입을 바탕으로 주입할 객체를 탐색한다는 의미다.
주의점! @Inject도 @Autowired와 같이 필드 또는 메서드에 적용할 때는 반드시 디폴트 생성자가 필요하다.
단, @Inject는 @Autowired와 달리 required 속성을 지원하지 않는다.
@Autowired에는 의존 객체 주입 시 필수 여부를 지정할 수 있는 @Autowired(required = false)와 같은 속성이 있다.
@Resource처럼 Java의 javax.inject 패키지를 pom.xml에 추가해야 한다.
<!-- pom.xml에 추가-->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
Code language: HTML, XML (xml)
가. @Named
@Autowired가 같은 데이터 타입을 가진 bean이 여러 개 있는 경우 발생하는 문제를 @Qualifier로 풀었다면 @Inject는 @Named로 풀 수 있다.
<bean id="contactDao1" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao3" class="ch05_pjt_01.contact.dao.ContactDao" />
Code language: JavaScript (javascript)
@Inject
@Named("contactDao1")
private ContactDao contactDao;
Code language: CSS (css)
6. 정리

| Autowired | Inject | Resource | |
| 탐색 방법 | 데이터 타입 | 데이터 타입 | bean id, 이름 |
| 범위 | 생성자, 필드, 메서드 | 생성자, 필드, 메서드 | 필드, 메서드 |
| spring? java? | spring | java | java |
| 주입할 bean을 지정하는 법 | @Qualifier | @Named | @Qualifier |
| 기타 | required 속성 사용 가능 | required 속성 사용 불가능 |
