코린이의 기록

[Spring] Spring 4 - 의존 자동 주입 본문

Framework/Spring

[Spring] Spring 4 - 의존 자동 주입

코린이예요 2018. 5. 3. 12:06
반응형

※ 이 포스팅은 "초보웹 개발자를 위한 스프링4 프로그래밍 입문" 책을 기반으로 작성하였습니다.

이전 포스팅에서 "Spring 4 - 스프링 DI와 예제 프로젝트에서 DI에 대한 개념을 살펴보았다. 이번 포스팅에서는 DI에 대한 자동 주입 방법을 살펴볼 것이다. 

소스는 이전 포스팅에서 구현한 프로젝트를 동일하게 사용한다. 

1. @Autowired 애노테이션을 이용한 의존 자동 주입

우리가 spring 설정파일로 bean 객체를 생성하고 주입하였다. 

`<bean id = "memberDao" class="spring.MemberDao"></bean> <bean id = "memberRegSvc" class = "springMemberRegisterService"> <constructor-arg ref="memberDao"/> </bean>

이것을 자동 주입기능을 사용하면 아래와 같이 <constructor-arg> 태그나 <property> 태그를 사용하지 않아도 의존 객체가 주입된다. 
@Autowired 애노테이션을 이용한 자동 주입 방법
1. 주입 대상에 @Autowired 애노테이션 생성자 적용
2. xml 설정에서 <context:annotation-config/> 설정 추가하기

<bean id = "memberDao" class="spring.MemberDao"></bean> <bean id = "memberRegSvc" class = "spring.MemberRegisterService"> </bean>

@Authowired 애노테이션은 어디에 적용시켜야 할까? 바로 해당 의존 객체를 사용할 클래서에서 적용시키면 된다. 
MemberRegisterService에서 MemberDao객체를 의존하고 있으므로 @Autowired를 적용시켜준다.

 appCtx1.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <bean id="memberDao" class="spring.MemberDao"> </bean> <bean id="memberRegSvc" class="spring.MemberRegisterService"> </bean> <bean id="memberPrinter" class="spring.MemberPrinter"> </bean> <bean id="infoPrinter" class="spring.MemberInfoPrinter"> </bean> </beans>


appCtx.xml에 아래 두가지를 추가

xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context">
<context:annotation-config />

MemberRegisterService.java

// 생략 import org.springframework.beans.factory.annotation.Autowired; public class MemberRegisterService { private MemberDao memberDao; @Autowired public MemberRegisterService(MemberDao memberDao) { this.memberDao = memberDao; } // 생략 }

Ctrl + Shift + I를 누르면 org.springframework.beans.factory.annotation.Autowired가 자동으로 import 된다.

MemberInfoPrinter.java

package spring; import org.springframework.beans.factory.annotation.Autowired; public class MemberInfoPrinter { @Autowired private MemberDao memDao; private MemberPrinter printer; public void setMemberDao(MemberDao memberDao) { this.memDao = memberDao; } @Autowired public void setPrinter(MemberPrinter printer) { this.printer = printer; } public void printMemberInfo(String email) { Member member = memDao.selectByEmail(email); if (member == null) { System.out.println("데이터 없음\n"); return; } printer.print(member); System.out.println(); } }

memDao 객체애 대해 @Autowired 적용, setPrinter 설정 메소드에 @Autowired 적용하였다. 
위와 같이 @Autowired를 적용할 경우 xml 설정파일에서 <constructor-arg>나 <property>태그를 사용하지 않아도 된다.

 appCtx1.xml

// 생략 <bean id="memberDao" class="spring.MemberDao"></bean> // 생략 <bean id="memberPrinter" class="spring.MemberPrinter"></bean>

의존 자동 주입을 하지 않았을 경우 property 명시를 해주어야 한다.

1.1 동일한 타입을 가진 객체가 두개 있다면 어떻게 처리해야 할까?

MemberInfoPrinter.java

package spring; import org.springframework.beans.factory.annotation.Autowired; public class MemberInfoPrinter { @Autowired private MemberDao memDao; private MemberPrinter printer; public void setMemberDao(MemberDao memberDao) { this.memDao = memberDao; } @Autowired public void setPrinter(MemberPrinter printer) { this.printer = printer; } public void printMemberInfo(String email) { Member member = memDao.selectByEmail(email); if (member == null) { System.out.println("데이터 없음\n"); return; } printer.print(member); System.out.println(); } }

MemberInfoPrinter 클래스의 setPrinter 메소드는 MemberPrinter 타입의 의존 객체를 자동으로 주입받기 위하여 @Autowired를 사용했다. spring 설정에서 MemberPrinter타입으로 정의된 bean객체를 검색할 것이다. 그런데 아래 appCtx.xml을 보자

appCtx.xml

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:annotation-config /> <bean id="memberDao" class="spring.MemberDao"> </bean> <bean id="memberRegSvc" class="spring.MemberRegisterService"> </bean> <bean id="printer1" class="spring.MemberPrinter"> </bean> <bean id="printer2" class="spring.MemberPrinter"> </bean> <bean id="infoPrinter" class="spring.MemberInfoPrinter"> </bean> </beans>

MemberPrinter 타입의 빈 객체가 printer1, printer2 두개가 존재한다. 따라서 @Autowired를 정의하였지만 어떤 bean객체를 주입해야할지 모르니 exception이 발생하게 된다. 

이를 해결하기위해서는 @Qualifier 애노테이션을 이용하여 의존 객체를 선택할 수 있도록 한다.

1.2 @Qaulifier 애노테이션을 사용하여 의존 객체 선택하기

MemberInfoPrinter.java

@Autowired @Qualifier("sysout") public void setPrinter(MemberPrinter printer) { this.printer = printer; }

@Qualifier 애노테이션 값으로 "sysout"을 지정해주었다. 해당 값을 갖는 bean 객체의 <qualifier> 값을 찾아 주입알 의존 객체로 사용한다.
appCtx.xml

<bean id="printer1" class="spring.MemberPrinter"> <qualifier value="sysout"/> </bean>

printer1 이름의 bean 객체와 printer2 이름의 bean객체 중, printer1 이름의 객체에 qualifier 값으로 "sysout"을 설정해주었다. 따라서 setPrinter는 MemberPrinter 의존 객체중 printer1 bean 객체를 주입할 의존 객체로 사용할 것이다.

1.3 @Autowired 필수 여부 지정
@Autowired 애노테이션을 적용하려면 xml 에 주입할 의존 객체가 존재해야 한다.  하지만 xml 설정파일에 bean 객체가 존재하지 않는데 @Autowired 를 설정하면 exception이 발생한다. @Autowired 가 필수가 아님을 설정하기 위하여 required=false를 추가해주면 해당 애노테이션이 적용된 대상에 설정할 의존 객체가 없다고 하더라도 exception을 발생시키지 않게된다.
ex. @Autowired(required=false)

2. @Resource 애노테이션을 이용한 의존 자동 주입

@Autowired 애노테이션이 타입을 이요하여 주입할 객체를 검색한다면, @Resource 애노테이션은 bean 이름을 이용하여 주입할 객체를 검색한다. 

@Resource 애노테이션을 이용한 자동 주입 방법
1. 주입 대상에 @Resource 애노테이션 생성자 적용
2. xml 설정에서 <context:annotation-config/> 설정 추가하기

@Resource 애노테이션을 적용할때에는 bean객체 이름을 지정해주어야 한다.
ex. @Resource(name="[bean name])

MemberRegisterService.java

package spring; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired; public class MemberRegisterService { @Resource(name = "memberDao") private MemberDao memberDao; //@Autowired public MemberRegisterService(MemberDao memberDao) { this.memberDao = memberDao; } // 파라미터가 없는 기본 생성자 추가 public MemberRegisterService(){ } // 생략 }

@Resource 애노테이션은 필드나 메소드에만 적용할 수 있어서 주석처리되어 있는 @Autowired 생성자 부분에 적용하지 않고 MemberDao 필드에 적용하였다.

MemberInfoPrinter.java

package spring; import org.springframework.beans.factory.annotation.Autowired; public class MemberInfoPrinter { // @Autowired @Resource(name="memberDao") private MemberDao memDao; private MemberPrinter printer; public void setMemberDao(MemberDao memberDao) { this.memDao = memberDao; } //@Autowired @Resource(name="memberPrinter") public void setPrinter(MemberPrinter printer) { this.printer = printer; } // 생략 }
3. 자동 주입과 명시적 의존 주입간의 관계


의존성 주입에 대한 좋은 설명이 있어서 스크랩함


반응형
Comments