스프링 DI(의존주입)-2

1. 스프링에서의 의존주입 방식

  • 생성자 방식

기본적인 의존주입 방식은 ‘생성자 방식’이 있다.
생성자를 통해 의존 객체를 주입 받아 필드에 할당하는 방식이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class MemberRegisterService {
private MemberDao memberDao;

// 의존 객체를 할당해줄 생성자 메소드
public MemberRegisterService(MemberDao memberDao) {
this.memberDao = memberDao;
}

public void regist(RegisterRequest req) {
// 주입 받은 의존 객체를 메소드에서 사용함
Member member = memberDao.selecetByEmail(req.getEmail());
...
memberDao.insert(newMember);
}
}

1
2
3
4
5
<bean id="memberDao" class="kr.co.jhdev.Member.MemberDao"></bean>

<bean id="memberRegSvc" class="kr.co.jhdev.Member.MemberRegisterService">
<constructor-arg ref="memberDao" />
</bean>

위와 같이 constructor-arg 태그를 이용해 생성자에 의존 객체를 주입한다.
만약 생성자에 전달해야할 의존 객체가 두 개 이상이라면 constructor-arg 태그를 순서에 맞게 추가하고 생성자의 매개변수를 추가한다.

1
2
3
4
5
6
7
8
9
10
11
public class MemberRegisterService {
private MemberDao memberDao;
private MemberPrint memberPrint;

// 의존 객체를 할당해줄 생성자 메소드
public MemberRegisterService(MemberDao memberDao, MemberPrint memberPrint) {
this.memberDao = memberDao;
this.memberPrint = memberPrint;
}
...
}
1
2
3
4
5
6
7
<bean id="memberDao" class="kr.co.jhdev.Member.MemberDao"></bean>
<bean id="memberPrint" class="kr.co.jhdev.Member.MemberPrint"></bean>

<bean id="memberRegSvc" class="kr.co.jhdev.Member.MemberRegisterService">
<constructor-arg ref="memberDao" />
<constructor-arg ref="memberPrint" />
</bean>
  • 설정 메소드 방식

다음으로는 ‘설정 메소드 방식’이 있다.
set으로 시작하는 프로퍼티 설정 메서드를 통해 의존 객체를 주입하는 방식이다.
** 프로퍼티에 대한 내용은 별도로 포스트

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MemberRegisterService {
private MemberDao memberDao;
private MemberPrint memberPrint;

public void setMemberDao(MemberDao memberDao) {
this.memberDao = memberDao;
}

public void setMemberPrint(MemberPrint memberPrint) {
this.memberPrint = memberPrint;
}
...
}
1
2
3
4
5
6
7
<bean id="memberDao" class="kr.co.jhdev.Member.MemberDao"></bean>
<bean id="memberPrint" class="kr.co.jhdev.Member.MemberPrint"></bean>

<bean id="memberRegSvc" class="kr.co.jhdev.Member.MemberRegisterService">
<property ref="memberDao" name="memberDao"/>
<property ref="memberPrint" name="memberPrint"/>
</bean>

설정 메소드 방식은 각 필드의 getter/setter를 가지며 태그를 이용해 객체를 주입한다.

  • 그렇다면 이 두 가지 방식 중 어떤 방식이 좋은 방식일까?

결론은 양쪽 모두 장단점이 존재한다.

생성자 방식은 빈 객체 생성 시점에 모든 의존 객체가 주입되지만
주입해야할 객체가 많을 경우 생성자의 파라미터가 많아지고 가독성이 떨어진다.

반대로 설정 메소드 방식은 property 태그의 name 속성(attribute)를 통해
해당 의존 객체에 대해 알아볼 수 있으므로 가독성이 좋은 편이다.

하지만 설정 메소드 방식의 경우 property 태그가 누락될 경우 객체 사용 시점에 NullPointException을 발생 시킬 수 있다.

2. 객체 주입 시 기본 값 설정

생성자 방식과 설정 메소드 방식을 통해 의존 객체를 주입하는 방법을 알 수 있었다.
이와 같은 객체 주입 시 기본 데이터 값을 설정해야하는 경우 value 속성을 이용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class VersionPrint {
private int majorVersion;
private int minorVersion;

// setter
public void setMajorVersion(int majorVersion) {
this.majorVersion = majorVersion;
}

// setter
public void setMinorVersion(int minorVersion) {
this.minorVersion = minorVersion;
}

public void print() {
System.out.println("Version Num : " + majorVersion + "." + minorVersion);
}
}
1
2
3
4
5
6
<bean id="versionPrint" class="kr.co.jhdev.Version.versionPrint">
<property name="majorVersion" value="3"/>
<property name="minorVersion">
<value>7</value>
</property>
</bean>

생성자, 설정 메소드 두 방식 모두 value 속성을 통해 기본 값을 설정한다.
value 속성이 아닌 태그를 통해 중첩 사용하는 방법도 존재한다.

여기서 주목해야할 점은 해당 기본 값의 데이터 타입을 알 수 없음에도 정상 동작한다.
그 이유는 스프링이 알아서 데이터 타입으로 변환하여 처리하기 때문이다.

3. 두 개 이상의 설정파일 사용하기

개발을 하다보면 설정 관련 파일이 비대해질 수 있다.
이럴 경우 가독성도 떨어지게 되고 유지보수에 있어 어려움을 겪을 수 있다.

해당 문제점을 개선하기 위해선 설정 파일을 성격에 따라 나누어야 한다.
설정 파일을 나눈 경우 GenericXmlApplicationContext 클래스의 생성자를 이용하는 방법과 import 태그를 이용하는 방법이 있다.

  • GenericXmlApplicationContext의 생성자를 이용하는 방식
    기본적으로 GenericXmlApplicationContext 클래스의 생성자는 가변 인자이므로 배열을 이용할 수 있다.
1
2
String[] conf = {"classpath:conf1.xml", "classpath:conf2.xml"};
ctx = new GenericXmlApplicationContext(conf)

위와 같이 설정 xml 파일 경로를 배열에 담고 생성자에 전달하는 방식이다.

  • import 태그를 이용하는 방식
    import 태그를 이용하는 방식의 경우 설정파일을 분리 한 후 import 태그를 이용해
    한 설정 파일에 다른 설정 파일 내용을 삽입해주는 방법이다.
1
2
3
4
5
6
7
8
9
<import resource="classpath:conf2.xml />

<bean id="memberDao" class="kr.co.jhdev.Member.MemberDao"></bean>
<bean id="memberPrint" class="kr.co.jhdev.Member.MemberPrint"></bean>

<bean id="memberRegSvc" class="kr.co.jhdev.Member.MemberRegisterService">
<property ref="memberDao" name="memberDao"/>
<property ref="memberPrint" name="memberPrint"/>
</bean>

위와 같이 설정 파일 내용을 import 태그를 통해 다른 설정 파일에 추가하여 함께 사용할 수 있다.

Share