본문 바로가기

Backend/Spring & SpringBoot

[Spring Framework] 02. DI(Dependency injection)

728x90

2.1 DI와 IoC

IoC : Inversion of Control 제어의 역전, 프로그램을 제어하는 패턴 중 하나

 - DI는 IoC패턴을 구현하는 방법 중 하나이다. 

 - DI에 따라 프로그램의 흐름이 완전히 변경됨. 

 

DI : Dependency injection

 - 스프링 Container에 만들어둔 각종 클래스(bean) 들은 서로 의존적이다. 

 ex) a 객체가 b 객체 없이 동작을 못함

 

=> 스프링 프레임워크는 DI를 기준으로 많은 프레임워크 모듈이 만들어짐.

 

예시) 배터리에 의존해서 장남감을 만들었다

 

배터리 일체형 장난감 - 배터리가 떨어지면 장난감을 새로 구입해야됨.

배터리 분리형 장난감 - 배터리가 떨어지면 배터리만 교체하면됨.

배터리  탈부착형 장난감 - 배터리가 떨어지면 배터리만 교체하면됨.

=> 배터리에 의존적인 장난감. 

 

* 기존에 의존성 주입을 하지 않았을때는 어떻게 해야되는지?

 

* Hotel.java

package com.spring.basic.ex01;

public class Hotel {
	private Restaurant res;
	public Hotel(Restaurant res) {
		System.out.println("호텔이 생성됨");
		this.res =res;
	}
	public void reserveRestaurant() {
		System.out.println("레스토랑을 예약합니다.");
		res.orderDinner();
	}
}

* Restaurant.java

package com.spring.basic.ex01;

public class Restaurant {
	private Chef chef;
	public Restaurant(Chef chef) {
		System.out.println("레스토랑이 생성됨!");
		this.chef = chef;
	}
	public void orderDinner() {
		System.out.println("저녁 식사를 주문받습니다.");
		chef.cook();
	}
}

 

* Chef. java

package com.spring.basic.ex01;

public class Chef {
	public Chef() {
		System.out.println("요리사가 생성됨.");
	}
	
	public void cook() {
		System.out.println("요리사가 요리를 합니다.");
	}
}

* MainClass.java

package com.spring.basic.ex01;

public class MainClass {

	public static void main(String[] args) {
		Chef chef = new Chef();
		Restaurant res = new Restaurant(chef);
		Hotel hotel = new Hotel(res);
		hotel.reserveRestaurant();
	}

}

<실행결과>

=> 의존성 주입을 하지 않은 기존의 java를 사용할때는 이렇게 MainClass에서 처럼 생성자에 직접 객체를 넣어주어야한다. 

Chef chef = new Chef();
Restaurant res = new Restaurant(chef);
Hotel hotel = new Hotel(res);
hotel.reserveRestaurant();

 

하지만 Spring DI 를 활용하게 된다면 좀더 간결하게 처리 할 수 있다. 다음으로 어떻게 Spring 에서 의존성 주입을 하는지 보겠다.

 

2.2 DI 설정방법

스프링 컨테이너 생성 및빈(Bean)객체 호출과정

* 2가지 의존성 주입 방법

1) 생성자를 통한 의존성 주입

<constructor-arg  ref="id"></constructor-arg>

 

2) setter을 통한 의존성 주입

<property name="변수명"  value=""/>

<property name="변수명"  ref="객체"/>

 

* 스프링 설정파일에 추가

<beans xmlns="http://www.springframework.org/schema/beans" 
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">

xmlns:xsiXML정보를 가르키는 주소 

xmlns속성값은 네임스페이스로 태그를 식별하기 위한 이름

xsi:schemaLocation

두개의 값이 공백으로 구분 됨 / 첫번째는 사용할 네임스페이스/ 두번째는 참조할 네임스페이스 위치

 

* 앞서 Hotel 을 생성할때 의존성 주입을 어떻게 해야되는지 살펴보겠다.

- 생성자를 통한 의존성 주입을 하는 방식으로 보겠다. 앞서 설명한 것 처럼 스프링 설정파일에 추가해야한다. 

이 프로젝트에서는 config-test.xml 에 추가해야한다. 아래와 같이 설정한다. 

 

* config-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"  
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">

	<!-- Hotel 객체와 의존객체들의 빈 등록 및 의존성 주입 설정. -->
	<bean id="chef" class="com.spring.basic.ex01.Chef" />
	
	<bean id="res" class="com.spring.basic.ex01.Restaurant">
		<constructor-arg ref="chef" />
	</bean>
	
	<bean id="hotel" class="com.spring.basic.ex01.Hotel">
		<constructor-arg ref="res" />
	</bean>

</beans>

<constructor-arg ref="chef"/> 이부분은 앞에서 Hotel 클래스 에서 생성자를 만든 것 과 같은 역할을 한다. 

public Hotel(Chef chef) {

     this.chef = chef;

=>Hotel클래스를 hotel이름으로 bean생성 생성자 인자값으로 ref=chef 생성된 참조.

 

결과적으로 MainClass.java 에서 기존의 방식을 다음과 같이 고치면 의존성 주입이 된다.

 

* MainClass.java

package com.spring.basic.ex01;

import org.springframework.context.support.GenericXmlApplicationContext;

public class MainClass {

	public static void main(String[] args) {
		
//		Chef chef = new Chef();
//		Restaurant res = new Restaurant(chef);
//		Hotel hotel = new Hotel(res);
//		hotel.reserveRestaurant();
		
		GenericXmlApplicationContext ct = 
				new GenericXmlApplicationContext("classpath:test-config.xml");
		
		Hotel hotel = ct.getBean("hotel", Hotel.class);
		hotel.reserveRestaurant();
			
	}

}

 이전에 1강에서 배운것 처럼 GenGenericXmlApplicationContext 객체를 사용한다. 

 

<실행결과>

 

728x90