프로그래밍/Spring

[Spring] DI (Dependency Injection)에 대해 알아보자

byungmin 2020. 8. 13. 10:39

DI (Dependency Injection)

 

DI (Dependency Injection) 는 클래스 간의 의존관계를 빈-xml 파일정보를 바탕으로 컨테이너가 자동으로 연결해주는 것을 의미한다. 

 

 - 참조되는 객체 (class)를 직접 생성 (new) 하지 않고 컨테이너에 등록 (injection) 한 빈(객체)으로 불러와서 (lookup) 사용하는 방법이다.


스프링 컨테이너란?

 빈을 관리하는 저장소라고 생각하면 쉽다. 스프링 컨테이너는 빈 객체를 저장하고 있으며, 각 객체간의 의존 관계를 관리해준다. 

               

BeanFactory와 ApplicationContext가 컨테이너 역할을 수행하는 인터페이스


1) BeanFactory (인터페이스)
2) ApplicationContext (BeanFactory 를 상속받은 하위 인터페이스)


 - ApplicationContext를 구현할 클래스

ClassPathXmlApplicationContext,

FileSystemXmlApplicationContext,

AnnotationConfigApplicationContext,

GenericXmlApplicationContext 등이 있다.

 

3) 서버쪽에서는 WebApplicationContext (웹 어플리케이션을 위한 ApplicationContext)을 사용한다.

 

 - WebApplicationContext를 구현할 클래스

XmlWebApplicationContext,

AnnotationConfigWebApplicationContext 등이 있다.


DI 분류 체계

1) Setter Injection

<bean id="e1" class="ex04.empImpl">
	<property name="name" value="홍길동" />
    <property name="empno" value="7788" />
</bean>

2) Constructor Injection

<bean id="e2" class="ex05.EmpImple">
	<constructor-arg value="홍길동" />
</bean>

3) Method Injection

 

Setter Injection 사용하기

 - Emp Interface 생성

package ex04;

public interface Emp {
	void print1();
    void print2();
}

 - Emp Interface를 상속받는 EmpImpl 클래스 생성

package ex04;

import java.util.Random;

public class EmpImpl implements Emp {
	
	// property
	private int empno;
	private String name;
	private String dept;
    
    priavate Random ran;
    
  	// setter, getter
	
	public int getEmpno() {
		return empno;
	}

	public void setEmpno(int empno) {
		this.empno = empno;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDept() {
		return dept;
	}

	public void setDept(String dept) {
		this.dept = dept;
	}
    
    public Random getRan() {
		return ran;
	}

	public void setRan(Random ran) {
		this.ran = ran;
	}
    
    @Override
	public void print1() {
		System.out.println("Empno: "+empno);
		System.out.println("Name: "+name);
		System.out.println("Dept: "+dept);
	}
    
    @Override
	public void print2() {
		if(ran!=null) {
			System.out.printf("랜덤한 정수: %d\n", ran.nextInt(1000)); // 0~1000사이 값
		} else {
			System.out.println("Random객체 ran이 주입되지 않았어요.");
		}
	}
    
}

 - spring bean configuration file 생성 (empBean.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-4.3.xsd">

	<!-- [1] EmpImpl빈을 등록하세요 id="e1" -->
	<bean id="e1" class="ex04.EmpImpl"/> <!-- 스프링 컨테이너가 class의 기본생성자를 부른다. -->
    
    <!-- [2] EmpImpl빈을 등록하되, 사번, 이름, 부서명을 setter로 주입(injection)해보자. -->
	<bean id="e2" class="ex04.EmpImpl">
		<property name="name">
			<value>최진주</value>
		</property>
		<!-- e2.setName("최진주")와 동일 -->
		<property name="empno" value="7788" />
		<property name="dept" value="Sales" />
	</bean>
    
    <bean id="r" class="java.util.Random"/>
	
    <bean id="e3" class="ex04.EmpImpl">
    	<property name="ran">
        	<ref bean"r"/>
        </property>
    </bean>
    <!--
    	EmpImp e3 = new EmpImpl();
        e3.setRan(r) 
    -->

</beans>

empBean.xml 이 컨테이너 저장소가 된다.

1. 여기다가 우리가 만든 클래스(객체)를 등록하자

2. setter를 만들어서 bean을 사용할 때는 <property> 태그를 사용한다.

3. 정수, 실수, 문자열 값등을 setter로 주입할 때는 value 속성을 이용해 값을 주입한다.


* 참조유형일 경우  -> 객체를 먼저 등록한 후 ref속성을 이용해 주입한다.

LookUp을 통해 컨테이너에 저장된 빈 객체 사용하기

package ex04;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class SpringAppTest {
	public static void main(String[] args) {
		
		String config = "classpath:ex04/empBean.xml"; // lookup할 수 있는 객체를 생성
		ApplicationContext ctx = new GenericXmlApplicationContext(config);
		
		// e1을 찾아 print1()을 호출하세요.
		Emp  e1 = (Emp)ctx.getBean("e1"); // 반환타입이 object니까 형변환
		e1.print1(); // 값이 안들어가있다.
        
        Emp e3 = ctx.getBean("e3", Emp.class);
        e3.print2();
   	}
}

1. String config = "classpath:ex04/empBean.xml" 을 통해 lookUp할 수 있는 객체를 생성해준다.

(빈이 있는 경로를 잡아준다.)

2. ApplicationContext 객체를 만들어주고 config를 넣어준다.

3. xml 파일에서 설정한 id를 통해 이곳에서 불러올 수 있다.

4. ctx.getBean("e1") -> e1.print1();

 

결과

Empno: 7788
Name: 최진주
Dept: Sales
랜덤한 정수: 870