본문 바로가기
프로그래밍/Spring

[Spring] Dependency Injection(Constructor/Setter-based Injection)

by 소꿍 2020. 12. 13.

Dependency Injection 개요

 

의존관계(의존성) 주입

Spring Framework의 핵심 기능 중 하나로, 객체 간 의존 관계가 객체 자신이 아닌 외부에 의해 결정되는 개념이다.

 

컨테이너는 어떤 객체 A가 필요로 하는 의존관계에 있는 다른 객체 B를 직접 생성하여 객체 A로 주입해 주는 역할을 한다.

DI는 의존관계 구현을 어떻게 하는지에 대한 내용이다.

 

 

의존하는 객체를 지정하는 방법

  • 의존하는 객체를 코드에 직접 명시하는 방법(일반적인 방법)
    단위 테스트가 어렵고, 의존하는 객체 변경 시 코드를 수정해야 한다.

  • Factory나 JNDI를 이용해 검색하는 방법
    단위 테스트가 어렵고, 실제 의존하는 객체와의 의존성은 느슨하고 Factory나 JNDI와의 의존성이 생긴다.

 

 

XML 기반 설정 방법

객체 간 의존성을 설정 파일(Configuration xml)로 손쉽게 관리한다.
Spring은 클래스 간 의존관계를 관리하는 2가지 방법을 제공한다.

 

1. Constructor-based Injection

클래스에 생성자를 지정하고, 의존하는 객체를 생성자를 통해 전달한다.

필수(mandatory) 의존성 설정이 가능하다.

사용 방법이 가능하다.(한 줄에 생성, 주입 한꺼번에 가능)

 

2. Setter-based Injection(일반적으로 많이 사용하는 방법) - property

클래스에 set 메소드를 지정하고, 의존하는 객체를 set 메소드를 통해 전달한다.

옵션(optional)으로 의존성 설정이 가능하다.

어떤 의존 객체를 설정하는지를 메소드 이름으로 알 수 있다.

상속이 가능하다.

일반적으로 많이 사용되며, Spring에서 권장하는 방법이다.(많은 수의 생성자 인자는 관리가 어려우나, setter 메소드는 재구성하기 쉽다.)

 


Constructor-based Injection

1) 의존하는 객체를 전달받을 생성자를 작성한다.

 

2) 설정 파일(*.xml)에 <constructor-arg> 태그를 이용해 변수 이름과 값(value)을 설정한다.

그렇게 되면 <constructor-arg> 태그에 담은 데이터, 객체 등을 생성자로 전달하게 된다.

(객체인 경우 <ref>, 문자열이나 기본 데이터인 경우 <value> 태그 사용)

main에서 IoC 컨테이너 생성, getInfo() 메소드로 name을 출력해 보면 .xml에서 전달해 준 name값 홍길동이 출력된다.

 

※ 주의할 점

DTO 클래스에 생성자를 작성하고 기본 생성자를 별도로 적어주지 않은 경우 기본 생성자가 없어지기 때문에,
.xml에서 <bean class="com.dto.Student"/> 코드 작성 시 에러가 발생한다.(bean이 기본 생성자를 사용하기 때문)

--> 기본 생성자를 꼭 포함하도록 한다.

 

 

  • 생성자로 전달할 객체나 값이 여러 개인 경우에는 index를 사용한다.(index는 0부터 시작)
public class Person {
	public Person(String x) {
		System.out.println("Person 생성자 " + x);
	}
    
    public Person(String x, String y) {
    	System.out.println("Person 생성자 " + x + "\t" + y);
    }
}
<?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">

	<bean id="xxx" class="com.dto.Person">
    	<constructor-arg index="0" value="고양이"></constructor-arg>
        <constructor-arg index="1" value="강아지"></constructor-arg>
	</bean>
</beans>

 

  • 객체를 생성자에 지정할 경우에는 ref 속성을 사용한다.

Cat 클래스
Student 클래스
ref를 사용한 객체 주입

 


 

Setter-based Injection

property 설정 방식이라고도 한다.

 

1) 의존하는 객체를 전달받을 setter 메소드를 작성한다.

 

2) 설정 파일에 <property> 태그를 이용하여 설정한다.

setXXX 메소드의 이름을 통해 객체를 주입하므로, name 속성값과 setXXX의 이름이 일치해야 한다.

(아래 코드에서는 setName() 메소드와 <property name="name" value="홍길동">에서 이름이 name으로 같다.)

 

3) 오버로딩 생성자인 경우 반드시 기본 생성자를 명시해야 한다.

 

getInfo() 메소드를 호출해 name을 출력하면 홍길동이 출력된다.

 

  • 여러 개의 객체를 주입할 때도 property를 사용하는데, 설정이 안 된 값은 초기값으로 설정된다.

 

  • 클래스에서 기본 데이터 타입을 설정하면 컨테이너가 타입 변환을 해 준다.

    아래 코드를 보면 Student 클래스에서 생성자 안에 age의 타입을 int로 선언했기 때문에,
    value인 "20"이 int 타입으로 변환되어 설정된다.

 

 

 

  • ref를 사용해 객체 주입하기

 

Cat 클래스에서도 반드시 Setter 메소드를 정의해야 한다.

ref 태그를 사용해 Cat 객체를 Student 클래스의 Cat에 주입하고 있다.

 

  • property 태그 없이 값 설정하는 방법
    .xml의 Namespaces에서 p에 체크한다.

이때도 반드시 클래스에 setter 메소드를 정의해 주어야 한다.

property 태그가 아닌 p를 사용해 값을 설정한다.(bean 태그 안에서 설정하고 있음. 주의!)

객체인 경우에는 p:프로퍼티명-ref="참조값"으로 설정하고, 문자열이나 기본값은 p:프로퍼티명="값" 형식으로 설정한다.

 

  • Setter, Constructor Injection 혼용

 

property와 contructor-arg를 모두 사용하고 있다.

 

 

댓글