@Autowired를 이용한 의존 객체 자동 주입
생성자가 여러 개인 경우
Serivce빈이 생성될 때 생성자에 ContactDao가 자동 주입되는 것을 확인했다.
만약 새성자가 오버라이드되어 여러 개가 있다면 어떻게 될까?
이를 확인하기 위해 Service클래스에 디폴트 생성자를 추가하고 실행해보면 다음과 같다.
■ ContactRegisterService 클래스 생성자
public ContactRegisterService() {
System.out.println("default constructor");
}
public ContactRegisterService(ContactDao contactDao) {
System.out.println("contactDao: " + contactDao);
this.contactDao = contactDao;
}
■ ContactSearchService 클래스 생성자
public ContactSearchService() {
System.out.println("default constructor");
}
public ContactSearchService(ContactDao contactDao) {
System.out.println("contactDao: " + contactDao);
this.contactDao = contactDao;
}
이처럼 디폴트(defualt) 생성자가 추가된 클래스가 실행되는 것을 확인할 수 있다.
→ appCtx.xml에서 <bean>태그에 <constructor-arg/>을 사용하지 않았기 때문이다.
이렇게 오버라이드된 경우 CantactDao가 Service 객체에 자동 주입되게 하려면 @Autowired 애너테이션을 명시하면 된다.
@Authowired 애너테이션은 생성자 또는 메서드에 주입하면 된다.
· 생성자에 주입하는 경우
@Autowired
public ContactSearchService(ContactDao contactDao) {
System.out.println("contactDao: " + contactDao);
this.contactDao = contactDao;
}
· 필드에 주입하는 경우
@Autowired
private ContactDao contactDao;
· 메서드에 주입하는 경우
@Autowired
public void setWordDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
@Resource를 이용한 의존 객체 자동 주입
@Autowired와 @Resource의 차이점
@Autowired | @Resource |
· 데이터 타입을 이용한 의존 객체 자동 주입 · 필드, 생성자, 메서드, 사용 가능 |
· 빈 객체의 이름을 이용한 의존 객체 자동 주입 · 필드, 메서드에 사용 가능(생성자 사용 불가능) |
@Resource 적용 대상
필드에 @Resource 적용
- @Resource : @Autowired와 달리 스프링이 아닌 자바에서 제공하는 애너테이션으로 관련 모듈을 pom.xml에 설정해야한다.
- javax.annotation-api 모듈을 pom.xml에 추가한다.
1. 메인 레포지토리에 접속하여 javax.annotation-api 모듈을 검색 후 Javax Annotation API를 선택한다.
2. Javax AnnotationAPI 페이지에서 1.3.2를 클릭한다. 클릭 후 나온 페이지에서 메이븐 코드를 복사한다.
3. 복사한 코드를 pom.xml에 붙여넣는다.
<!-- spring-context 모듈 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
javax.annotation-api를 추가했다면 @Resource를 이용해서 ContactRegisterService와 ContactSearchService에서 ContactDao를 필드에 자동 주입한다.
■ ContactRegisterService와 ContactSearchService 클래스
이때 앞에서 작성한 @Autowired는 주석처리하고 다음과 같이 수정해준다.
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import ch05_pjt_01.contact.ContactSet;
import ch05_pjt_01.contact.dao.ContactDao;
public class ContactRegisterService {
@Resource
private ContactDao contactDao;
메서드에 @Resource 적용
· @Resource를 메서드에 적용할 수 있다.
· ContactRegisterService와 ContactSearchService의 setter 메서드에 적용한다.
■ ContactRegisterService와 ContactSearchService 클래스
@Resource
public void setWordDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
실행결과와 같이 ContactDao 객체가 setContactDao() 메서드에 자동 주입되어 정상 실행되었음을 알 수 있다.
@Resource는 생성자에 적용할 수 없다!!
다수의 빈 객체 중 의존 대상 객체 선택 방법
📣 만약 자동 주입 대상 객체가 2개 이상이면 어떻게 될까?
자동 주입 대상 객체가 2개 이상인 경우
다음과 같이 3개 (contactDao1, contactDao2, contactDao3)의 DAO 객체가 있다면 에러가 발생한다.
<bean id="contactDao" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao1" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
@Autowired는 객체 타입을 찾아서 자동으로 의존 객체를 주입한다.
따라서 동일한 타입의 의존 객체가 2개 이상인 경우에는 어떤 의존 객체를 자동 주입해야 하는지 판단할 수 없다.
이런경우 의존 대상 객체를 개발자가 지정해주면 된다.
<bean id="contactDao" class="ch05_pjt_01.contact.dao.ContactDao">
<qualifier value="usedDao"/>
</bean>
<bean id="contactDao1" class="ch05_pjt_01.contact.dao.ContactDao" />
<bean id="contactDao2" class="ch05_pjt_01.contact.dao.ContactDao" />
<qualifier> 태그 : 의존 대상 객체로 지정한다.
appCtx.xml에 <qualifier> 태그를 추가했다면 의존 객체가 자동 주입되는 ContactRegisterService와 ContactSearchService에 @Qualifier 애너테이션을 추가해주어야 한다.
이때 @Autowired와 @Resource 중 어느 쪽을 사용해도 상관없다.
■ @Autowired와 @Qualifier를 이용한 특정 의존 객체 지정
package ch05_pjt_01.contact.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ch05_pjt_01.contact.ContactSet;
import ch05_pjt_01.contact.dao.ContactDao;
public class ContactSearchService {
@Autowired
@Qualifier("usedDao")
private ContactDao contactDao;
■ @Resource와 @Qualifier를 이용한 특정 의존 객체 지정
package ch05_pjt_01.contact.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import ch05_pjt_01.contact.ContactSet;
import ch05_pjt_01.contact.dao.ContactDao;
public class ContactRegisterService {
@Autowired
@Qualifier("usedDao")
private ContactDao contactDao;
생성자 또는 멤버의 이름이 빈의 id와 같은 경우
· 빈의 id와 동일한 이름을 사용한 @Autowired 및 @Resource가 적용된 사용자 또는 멤버가 있다면 <qualifier>와 @Qualifier를 이용하지 않아도 의존 객체가 자동으로 주입된다.
■ appCtx.xml
<bean id="contactDao" 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" />
■ ContactRegisterService와 ContactSearchService 클래
@Autowired
//@Qualifier("usedDao")
private ContactDao contactDao;
매개변수 개수가 2개 이상인 경우
· 매개변수 개수가 2개 이상일 때도 의존 객체 자동 주입은 가능하다.
· 주입 대상 매개변수에 @Qualifier를 적용하면 된다.
■ appCtx.xml
<bean id="firstBean1" class="ch05_pjt_01.contact.service.FirstBean">
<qualifier value="usedBean" />
</bean>
<bean id="firstBean2" class="ch05_pjt_01.contact.service.FirstBean"/>
<bean id="firstBean3" class="ch05_pjt_01.contact.service.FirstBean"/>
<bean id="secondBean" class="ch05_pjt_01.contact.service.SecondBean"/>
<bean id="thirdBean" class="ch05_pjt_01.contact.service.ThirdBean"/>
<bean id="fourthBean1" class="ch05_pjt_01.contact.service.FourthBean">
<qualifier value="usedBean" />
</bean>
<bean id="fourthBean2" class="ch05_pjt_01.contact.service.FourthBean"/>
<bean id="fourthBean3" class="ch05_pjt_01.contact.service.FourthBean"/>
<bean id="autoWiredEx" class="ch05_pjt_01.contact.service.AutoWiredEx"/>
■ AutoWiredEx.java
package ch05_pjt_01.contact.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
public class AutoWiredEx {
@Autowired
public AutoWiredEx(@Qualifier("usedBean") FirstBean fBean, SecondBean sBean) {
System.out.println("fBean: " + fBean);
System.out.println("sBean: " + sBean);
}
@Autowired
public void autowiredMethod(ThirdBean tBean, @Qualifier("usedBean") FourthBean fBean) {
System.out.println("tBean: " + tBean);
System.out.println("fBean: " + fBean);
}
}
각각의 FirstBean, SecondBean, ThirdBean, FourthBean 클래스를 생성해준다.
구조도 | 실행결과 |
![]() |
![]() |
의존 객체 자동 주입 시 필수 여부 확인하기
· 빈을 생성하지 않고 @Autowired를 사용하면 의존 객체 자동 주입하는 과정에서 의존 객체를 찾을 수없어 에러가 뜬다.
· 에러가 발생하지 않게 하기 위해서는 required 속성을 이용한다.
· @Autowired에 required 속성을 false로 지정하면 의존 객체 자동 주입이 필수가 아닌 필요에 따라서 주입된다.
· 이러한 경우는 드물다.
@Autowired(required = false)
private ContactDao contactDao;
💡 required = false
주입 대상객체가 없어도 에러를 발생시키지 않는다는 의미
즉, 의존 주입 대상 객체가 설정되어 있다면 required=false라고 해도 자동으로 의존 객체가 주입된다.
@Inject를 이용한 의존 객체 자동 주입
@Autowired와 동일하게 @Inject 애너테이션을 이용해서 의존 객체를 자동으로 주입할 수 있다.
@Autowired | @Inject |
· required 속성을 이용해서 의존 객체가 없어도 에러를 피할 수있다. · 스프링에서 제공하는 애너테이션 |
· required 속성을 지원하지 않는다. · 자바에서 제공하는 애너테이션으로 pom.xml 설정이 필요 |
메인 리포지터리에 접속하여 javax.inject 모듈을 검색한 후 메이븐(maven) 코드를 복사해 pom.xml에 붙여넣는다.
■ pom.xml
<!-- spring-context 모듈 -->
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>1</version>
</dependency>
</dependencies>
이제 @Inject를 이용하여 의존 객체를 자동으로 주입해본다.
■ ContactRegisterService 클래스
//필드 자동 주입
@Inject
private ContactDao contactDao;
// 생성자 자동 주입
@Inject
public ContactRegisterService(ContactDao contactDao) {
this.contactDao = contactDao;
}
■ ContactSearchService 클래스
@Inject
private ContactDao contactDao;
@Inject
public ContactSearchService(ContactDao contactDao) {
this.contactDao = contactDao;
}
자동 주입 대상 객체가 2개 이상인 경우
@Autowired | @Inject |
@Qualifier 애너테이션 사용 | @Named 애너테이션 사용 |
■ appCtx.xml
<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" />
■ ContactRegisterService 클래스
//필드 자동 주입
@Inject
@Named("contactDao1")
private ContactDao contactDao;
// 생성자 자동 주입
@Inject
@Named("contactDao1")
public ContactRegisterService(ContactDao contactDao) {
this.contactDao = contactDao;
}
// 메서드 자동 주입
@Inject
@Named("contactDao1")
public void setWordDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
■ ContactSearchService 클래스
@Inject
@Named("contactDao1")
private ContactDao contactDao;
@Inject
@Named("contactDao1")
public ContactSearchService(ContactDao contactDao) {
this.contactDao = contactDao;
}
@Inject
@Named("contactDao1")
public void setContactDao(ContactDao contactDao) {
this.contactDao = contactDao;
}
디폴트 생성자가 없어서 에러가 발생하는 경우
· @Autowired를 적용할 때 필드 또는 메서드에 반드시 디폴트 생성자가 필요한 것과 같이 @Inject도 동일하다!·
· 디폴트 생성자가 있어야 정상적으로 빈이 생성되고 의존 객체를 자동 주입될 수 있다.
■ ContactRegisterService 클래스
//필드 자동 주입
@Inject
@Named("contactDao1")
private ContactDao contactDao;
// 생성자 자동 주입
// @Inject
// @Named("contactDao1")
public ContactRegisterService(ContactDao contactDao) {
this.contactDao = contactDao;
}
■ ContactSearchService 클래스
@Inject
@Named("contactDao1")
private ContactDao contactDao;
// @Inject
// @Named("contactDao1")
public ContactSearchService(ContactDao contactDao) {
this.contactDao = contactDao;
}
'Spring & Springboot > 올인원 스프링 프레임워크' 카테고리의 다른 글
Java 파일 분리와 @Import 애너테이션 (0) | 2023.09.20 |
---|---|
XML 파일을 Java 파일로 변경하기 (0) | 2023.09.20 |
스마트폰 연락처 -1 (0) | 2023.09.17 |
학사 관리 시스템 -4 (0) | 2023.09.14 |
학사 관리 시스템 -3 (0) | 2023.09.14 |