프로그래밍/Spring

[Spring] Constructor Injection에 대해 알아보자

byungmin 2020. 8. 13. 13:47

Constructor Injection

생성자를 이용하여 클래스 사이의 의존 관계를 연결하는 방법이다.

setter injection의 경우 컨테이너 (xml파일) 에 <property> 태그를 통해 값을 넣어줬다면,

constructor injection은 <constructor-arg> 태그를 통해 값을 넣는다.

 

 

앞서 포스팅 했던 DI 참고

[프로그래밍/Spring] - 알기 쉬운 Spring DI (Dependency Injection)에 대해 알아보자

DI 분류 체계

1) Setter Injection

 - 기본 생성자를 통해 접근

2) Constructor Injection

 - 기본 생성자가 없다면 인자생성자를 통해 접근


Constructor Injection 사용하기

- Emp interface 생성

package ex05;

public interface Emp {
	void info1();
	void info2();
	void info3();
	void info4();
}

 - EmpImple 클래스 생성 (Emp interfece 상속)

 

생성자를 오버로드하여 여러개 생성해보자.

package ex05;

import java.util.Random;

public class EmpImple implements Emp {
	
	private String name;
	private String dept;
	private int empno;
	
	private Random ran;
	
	public EmpImple() {
		
	}
	
    // 생성자 1
	public EmpImple(Random ran) {
		this.ran=ran;
	}
	
    // 생성자 2
	public EmpImple(String name) {
		this.name = name;
	}
	
    // 생성자 3
	public EmpImple(String name, int empno) {
		this(name);
		this.empno = empno;
	}
	
    // 생성자 4
	public EmpImple(int empno, String name) {
		this(name);
		this.empno = empno;
	}
	
    // 생성자 5
	public EmpImple(int empno, String name, String dept) {
		this(name, empno);
		this.dept = dept;
	}

	@Override
	public void info1() {
		// TODO Auto-generated method stub
		System.out.printf("Name: %s\n", name);
		
	}

	@Override
	public void info2() {
		// TODO Auto-generated method stub
		System.out.printf("Name: %s\n", name);
		System.out.printf("Empno: %s\n", empno);

	}

	@Override
	public void info3() {
		// TODO Auto-generated method stub
		System.out.printf("Name: %s\n", name);
		System.out.printf("Empno: %s\n", empno);
		System.out.printf("Dept: %s\n", dept);

	}

	@Override
	public void info4() {
		// TODO Auto-generated method stub
		if(ran!=null) {
			int num = ran.nextInt(500)+300;
			System.out.println("num="+num);
		} else {
			System.out.println("Random객체가 주입되지 않았어요!!");
		}

	}

}

 - 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">
	
	<!-- 기본 생성자가 아닌 인자생성자로 부르기 -->
	<bean id="obj1" class="ex05.EmpImple" >
		<!-- <constructor-arg>
			<value>홍길동</value>
		</constructor-arg> -->
		<constructor-arg value="홍길동" /> 
	</bean>
	<!-- EmpImple obj1 = new EmpImple("홍길동") 과 같다. -->
	
	<!-- obj2빈을 등록. 강길동, 7369 -->
	<!-- 인자 갯수는 같은데 순서가 다른 오버로드를 했을 경우  <index, type속성 사용> -->
	<bean id="obj2" class="ex05.EmpImple">
		<constructor-arg value="강길동" index="0" type="String" />
		<constructor-arg value="7369" index="1" type="int" />
	</bean>
	
	<!-- obj3등록. 사번, 이름, 부서명 -->
	<bean id="obj3" class="ex05.EmpImple">
		<constructor-arg value="이길동" index="1" type="String" />
		<constructor-arg value="3242" index="0" type="int" />
		<constructor-arg value="Sales" index="2" type="String" />
	</bean>
	
	<!-- Random 객체 빈으로 등록 -->
	<bean id="r" class="java.util.Random" />
	
	<!-- obj4등록 Random 객체를 생성자로 주입하기 -->
	<bean id="obj4" class="ex05.EmpImple">
		<constructor-arg  ref="r" />
	</bean>

</beans>

1. 생성자로 injection 할 경우 컨테이너는 자동으로 기본생성자가 아닌 인자를 가지고 있는 생성자를 통해 주입한다.

 

<constructor.arg> 태그의 속성

 

index : 생성자 몇 번째 인수에 값을 전달할 것인지 지정

type : 생성자의 어떤 자료형 인수에 값을 전달할 것인지 지정

ref : 주입할 참조 객체를 지정

value : 주입할 값을 지정

 

2. value 속성을 통해 값을 넣어준다.

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

이를 객체를 생성(new)해서 사용하는 코드 

EmpImple obj1 = new EmpImple("홍길동") 과 같다.

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

package ex05;

public class SpringAppTest {
	public static void main(String[] args) {
    	
        String config = "src/main/java/ex05/empBean.xml";
		// 프로젝트 기준으로 파일이 있는 경로
		
		ApplicationContext ctx = new FileSystemXmlApplicationContext(config);
		
		// 룩업할 때는 결합도 느슨하게 하기 위해 인터페이스 유형으로 부른다.
		Emp e1 = ctx.getBean("obj1", Emp.class);
		
		e1.info1();
    }
}

1.컨테이너 저장소(xml파일)가 있는 경로를 config로 받아주고 Lookup하기 위해

ApplicationContext 객체를 만들어준다.

2. 생성자 injection 과 같이 xml파일에서 <bean>태그에서 설정한 id를 통해 불러올 수 있다.

3. ctx.getBean("obj1", Emp.class); 

 

결과

Name: 홍길동

 

나머지 <bean> 태그로 입력한 객체들을 다 불러와보자

Emp e2 = ctx.getBean("obj3", Emp.class);
		
e2.info2();
		
ctx.getBean("obj3", Emp.class).info3();
		
ctx.getBean("obj4", Emp.class).info4();

결과

// obj1
Name: 홍길동
// obj2
Name: 이길동
Empno: 3242
// obj3
Name: 이길동
Empno: 3242
Dept: Sales
// obj4
num=659