[Spring] 스프링의 의존성 주입
의존성 주입 방법에는 두 가지가 있다. setter
메소드를 이용해서 의존성을 주입하는 방식과, constructor
생성자 메소드를 이용해서 의존성을 주입하는 방식이다. 두 방식에서 공통적으로 들어가야 하는 부분은 의존성 주입을 통해 전달받은 객체를 저장하는 변수인데, 이 멤버변수의 타입은 의존성 주입을 받는 객체의 부모타입도 가능하다. (ex. interface 클래스)
아래 예제에서 사용되는 클래스들은 모두 예제용이니 어떤 방식으로 이용되는지 참고만 하도록 하자.
setter 주입
public class SampleController {
UserService userService;
}
// 의존하는 객체를 전달하는 setter 메소드이다
public void setUserService(UserService userService) {
this.userService = userService;
}
- 아래 코드는 빈 설정파일(bean configuration file)이다.
<bean id="userServiceImpl" class="com.sample.service.UserServiceImpl"></bean>
<!--
첫번째 방법. property 태그 사용
name: setter 메소드 이름
ref : setter 메소드의 매개변수로 전달되는 객체의 빈 아이디
-->
<bean id="setterController" class="com.sample.controller.SampleSetterController">
<property name="userService" ref="userServiceImpl"></property>
</bean>
<!--
두번째 방법. p 속성 사용
p:setter메소드이름-ref="스프링 컨테이너에 보관 중인 객체의 아이디"
-->
<bean id="controller" class="com.sample.controller.SampleController"
p:userService-ref="userServiceImpl">
</bean>
constructor 주입
- 생성자 메소드를 이용해 의존성 주입을 받는 객체에는 반드시 constructor-arg 태그의 개수와 동일한 매개변수를 가지는 생성자가 정의되어 있어야 한다.
public class SampleController {
UserService userService;
// 의존하는 객체를 전달받을 생성자 메소드
public SampleController(UserService userService, ProductService productService) {
this.userService = userService;
this.productService = productService;
}
}
<bean id="userServiceImpl" class="com.sample.service.UserServiceImpl"></bean>
<!--
첫번째 방법. constructor-arg 태그 사용
name : 생성자 메소드의 매개변수 이름
ref : 스프링 컨테이너에 보관중인 객체의 아이디
-->
<bean id="controller" class="com.sample.controller.SampleController">
<constructor-arg name="userService" ref="userServiceImpl"></constructor-arg>
</bean>
<!--
두번째 방법. c 속성 사용
c:생성자 매개변수 이름-ref="스프링 컨테이너에 보관중인 객체의 아이디"
-->
<bean id="sampleController" class="com.sample.controller.SampleConstructorController"
c:userService-ref="userServiceImpl"></bean>
의존성 주입 대상
- 객체 타입
- 스프링 컨테이너가 생성/보관/조립하는 객체를 말한다.
- bean 태그나 지정된 패키지를 스캔해서 스프링 컨테이너에 등록된 객체다.
- 다른 객체에 조립될 때 ref 속성을 사용한다.
<property name="setter메소드이름" ref="빈의 아이디"/>
- Collection 타입
- 기본자료형값이나 스프링 컨테이너가 생성/보관/조립하는 객체를 여러 개 저장하고 있는 객체를 말한다.
- 배열, Set, List 등이다.
- setter / constructor 주입을 통해 의존성 주입이 가능하다.
public class SampleController {
String[] urls;
Set<MessageService> messageServices;
List<ExceptionHandler> exceptionHandlers;
public void setUrls(String[] urls urls) { this.urls = urls; }
public void setMessageServices(Set<MessageService> messageServices) { this.messageServices = messageServices; }
public void setExceptionHandlers(List<ExceptionHandler> exceptionHandlers) { this.exceptionHandlers = exceptionHandlers; }
}
<bean id="sampleController" class="com.sample.SampleController">
<property name="urls">
<array> <!-- 아래의 값을 담을 배열객체를 생성시킨다. -->
<value>http://www.daum.net</value>
<value>http://www.naver.com</value>
</array>
</property>
<property name="messageServices">
<set> <!-- 아래의 객체를 담을 Set구현객체를 생성시킨다. -->
<ref bean="smsMessageService"/>
<ref bean="emailMessageService"/>
</set>
</property>
<property name="exceptionHandler">
<list> <!-- 아래의 객체를 담을 List구현객체를 생성시킨다. -->
<ref bean="runtimeExceptionHandler"/>
<ref bean="DataAccessExceptionHandler"/>
</list>
</property>
</bean>
- Map 타입
- 기본자료형값이나 스프링 컨테이너가 생성/보관/조립하는 객체를 key, value의 쌍으로 여러 개 저장하는 객체다.
- 조건식의 상수값을 Map 객체의 key로 활용하면 조건식을 없앨 수 있다.
public class SampleController {
Map<String, MessageService> messageServices;
public void setMessageSerivces(Map<String, MessageService> messageServices){ this.messageServices = mnessageSerivices; }
public void execute(String key, String message) {
MessageService service = messageServices.get(key);
service.send(message);
}
}
<bean id="sampleController" class="com.sample.sampleController">
<property>
<map>
<entry key="sms" value-ref="smsMessageServiceImpl" />
<entry key="email" value-ref="emailMessageServiceImpl" />
</map>
</property>
</bean>
- 기본자료형 타입
- int, double, boolean, String 등이다.
- 다른 객체에 조립될 때 value 속성을 사용한다.
<property name="setter메소드이름" value="기본자료형값"></property>
<bean id="sampleController" class="com.sample.controller.SampleValueController">
<property name="host" value="192.168.10.2"></property>
<property name="port" value="3000"></property>
</bean>