시작하세요! 스프링 4 프로그래밍 : 스프링 코어부터 웹 mvc, 스프링...

80

Post on 22-Jul-2016

322 views

Category:

Documents


6 download

DESCRIPTION

애쉬쉬 사린, 제이 샤마 지음 | 최민석 옮김 | 오픈소스 & 웹 시리즈 _ 063 | ISBN: 9788998139643 | 30,000원 | 2014년 08월 20일 발행 | 592쪽

TRANSCRIPT

시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

지은이 애쉬쉬 사린, 제이 샤마

옮긴이 최민석

펴낸이 박찬규 엮은이 이대엽 디자인 북누리 표지디자인 아로와 & 아로와나

펴낸곳 위키북스 전화 031-955-3658, 3659 팩스 031-955-3660

주소 경기도 파주시 문발로 115 세종출판벤처타운 311호

가격 30,000 페이지 592 책규격 188 x 240mm

초판 발행 2014년 08월 20일

ISBN 978-89-98139-64-3 (13000)

등록번호 제406-2006-000036호 등록일자 2006년 05월 19일

홈페이지 wikibook.co.kr 전자우편 [email protected]

Getting started with Spring Framework :

a hands-on guide to begin developing applications using Spring Framework

Copyright © 2014 by Ashish Sarin & J Sharma

Korean edition copyright © 2014 by WIKIBOOKS.

All rights reserved.

이 책의 한국어판 저작권은 저작권자와의 독점 계약으로 위키북스가 소유합니다.

신 저작권법에 의해 한국 내에서 보호를 받는 저작물이므로 무단 전재와 복제를 금합니다.

이 책의 내용에 대한 추가 지원과 문의는 위키북스 출판사 홈페이지 wikibook.co.kr이나

이메일 [email protected]을 이용해 주세요.

이 도서의 국립중앙도서관 출판시도서목록 CIP는

서지정보유통지원시스템 홈페이지(http://seoji.nl.go.kr)와

국가자료공동목록시스템(http://www.nl.go.kr/kolisnet)에서 이용하실 수 있습니다.

CIP제어번호 CIP2014023114

시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

IV

목 차

01. 스프링 프레임워크 소개

1-1 소개.................................................................................................................................................................................. 18

1-2 스프링 프레임워크 모듈................................................................................................................................................ 19

1-3 스프링 IoC 컨테이너...................................................................................................................................................... 20

1-4 스프링 프레임워크의 장점............................................................................................................................................ 24

로컬.및.전역.트랜잭션을.일관된.방법으로.관리...................................................................................................... 24

선언식.트랜잭션.관리................................................................................................................................................... 27

보안.................................................................................................................................................................................. 27

JMX(Java.Management.Extensions).................................................................................................................. 28

JMS(Java.Message.Service)................................................................................................................................... 31

캐시.................................................................................................................................................................................. 32

1-5 간단한 스프링 애플리케이션........................................................................................................................................ 33

애플리케이션.객체와.그것의.의존성.식별하기........................................................................................................ 33

식별한.애플리케이션.객체에.해당하는.POJO.클래스.만들기............................................................................... 34

구성.메타데이터.작성................................................................................................................................................... 35

스프링.컨테이너의.인스턴스.생성.............................................................................................................................. 42

스프링.컨테이너의.빈에.접근하기.............................................................................................................................. 43

1-6 스프링 기반의 다른 프레임워크 프로젝트.................................................................................................................. 45

1-7 요약.................................................................................................................................................................................. 45

02. 스프링 프레임워크 기초

2-1 소개.................................................................................................................................................................................. 46

2-2 인터페이스 기반 프로그래밍 설계 원칙...................................................................................................................... 46

시나리오:.의존.클래스가.의존성의.구상.클래스를.참조하는.경우....................................................................... 47

시나리오:.의존.클래스가.의존성이.구현하는.인터페이스.참조를.사용하는.경우............................................. 48

인터페이스.기반.프로그래밍.설계.방법을.위한.스프링.지원................................................................................ 49

V

목 차

2-3 스프링 빈을 인스턴스화하는 다른 방법......................................................................................................................52

정적.팩터리.메서드를.이용한.빈.인스턴스화........................................................................................................... 53

인스턴스.팩터리.메서드를.이용한.빈.인스턴스화................................................................................................... 55

2-4 의존성 주입 기법............................................................................................................................................................57

세터.기반.DI................................................................................................................................................................... 57

생성자.기반.DI............................................................................................................................................................... 62

2-5 빈의 범위.........................................................................................................................................................................66

싱글톤.............................................................................................................................................................................. 66

프로토타입...................................................................................................................................................................... 77

빈의.올바른.범위.선택.................................................................................................................................................. 78

2-6 요약..................................................................................................................................................................................79

03. 빈 구성

3-1 소개..................................................................................................................................................................................80

3-2 빈 정의 상속....................................................................................................................................................................81

MyBank.–.빈.정의.상속.예제...................................................................................................................................... 81

상속되는.정보................................................................................................................................................................. 84

3-3 생성자 인자 연결............................................................................................................................................................90

<constructor-arg>.요소를.이용한.간단한.값.및.빈.참조.전달............................................................................ 91

형식을.기준으로.한.생성자.인자.연결....................................................................................................................... 92

이름을.기준으로.한.생성자.인자.연결....................................................................................................................... 98

3-4 다른 형식의 빈 속성 및 생성자 인자 구성.................................................................................................................102

스프링에서.기본.제공하는.속성.편집기..................................................................................................................103

다양한.컬렉션.형식의.값.지정...................................................................................................................................107

배열의.값.지정.............................................................................................................................................................114

<list>,.<set>,.<map>.요소의.기본.컬렉션.구현...................................................................................................115

VI

목 차

3-5 기본 제공되는 속성 편집기.........................................................................................................................................116

CustomCollectionEditor.........................................................................................................................................116

CustomMapEditor....................................................................................................................................................119

CustomDateEditor...................................................................................................................................................120

3-6 스프링 컨테이너에 속성 편집기 등록하기................................................................................................................121

PropertyEditorRegistrar.구현.만들기...................................................................................................................121

CustomEditorConfigurer.클래스.구성.................................................................................................................122

3-7 p 및 c 네임스페이스를 이용해 간결하게 빈 정의 작성하기....................................................................................123

p.네임스페이스............................................................................................................................................................124

c.네임스페이스.............................................................................................................................................................125

3-8 스프링의 util 스키마.....................................................................................................................................................128

<list>..............................................................................................................................................................................129

<map>...........................................................................................................................................................................131

MapFactoryBean.......................................................................................................................................................133

<properties>...............................................................................................................................................................136

<constant>..................................................................................................................................................................137

<property-path>........................................................................................................................................................139

3-9 FactoryBean 인터페이스............................................................................................................................................141

MyBank.애플리케이션.–.데이터베이스에.이벤트.저장하기...............................................................................142

MyBank.–.FactoryBean.예제..................................................................................................................................143

팩터리.빈.인스턴스에.접근하기................................................................................................................................148

3-10 요약..............................................................................................................................................................................150

04. 의존성 주입

4-1 소개................................................................................................................................................................................151

4-2 내부 빈...........................................................................................................................................................................152

VII

목 차

4-3 depends-on 특성을 이용한 명시적인 빈 초기화 순서 지정...................................................................................154

MyBank.–.빈.간의.암시적.의존성............................................................................................................................154

암시적.의존성.문제.....................................................................................................................................................155

4-4.싱글톤.및.프로토타입.범위.빈의.의존성.........................................................................................................162

싱글톤.범위.빈의.의존성............................................................................................................................................162

프로토타입.범위.빈의.의존성....................................................................................................................................166

4-5 싱글톤 빈에서 프로토타입 빈의 새 인스턴스 얻기..................................................................................................170

ApplicationContextAware.인터페이스...............................................................................................................170

<lookup-method>.요소...........................................................................................................................................174

<replaced-method>.요소........................................................................................................................................178

4-6 의존성 자동 연결..........................................................................................................................................................183

byType..........................................................................................................................................................................183

constructor.................................................................................................................................................................185

byName........................................................................................................................................................................187

default/no...................................................................................................................................................................189

빈을.자동.연결에서.제외............................................................................................................................................190

자동.연결의.제한.........................................................................................................................................................192

4-7 요약................................................................................................................................................................................192

05. 빈과 빈 정의의 사용자 지정

5-1 소개................................................................................................................................................................................193

5-2 빈 초기화 및 삭제 논리 사용자 지정..........................................................................................................................193

스프링이.destory-method.특성으로.지정된.정리.메서드를.호출하게.하는.방법.........................................198

프로토타입.범위.빈의.정리.메서드..........................................................................................................................199

모든.빈의.기본.빈.초기화.및.삭제.메서드.지정.....................................................................................................200

InitializingBean.및.DisposableBean.수명.주기.인터페이스............................................................................200

JSR.250의.@PostConstruct.및.@PreDestroy.어노테이션..............................................................................201

VIII

목 차

5-3 BeanPostProcessor를 이용해 새로 생성된 빈 인스턴스와 상호작용하기...........................................................203

BeanPostProcessor.예제.-.빈.인스턴스의.유효성.검사.....................................................................................206

BeanPostProcessor.예제.-.빈.의존성.처리...........................................................................................................210

FactoryBean에.대한.BeanPostProcessor의.동작.방식.....................................................................................215

RequiredAnnotationBeanPostProcessor..........................................................................................................218

DestructionAwareBeanPostProcessor...............................................................................................................219

5-4 BeanFactoryPostProcessor를 활용한 빈 정의 수정................................................................................................220

BeanFactoryPostProcessor.예제...........................................................................................................................221

PropertySourcesPlaceholderConfigurer...........................................................................................................227

PropertyOverrideConfigurer.................................................................................................................................235

5-5 요약................................................................................................................................................................................238

06. 스프링 어노테이션 기반 개발

6-1 소개................................................................................................................................................................................239

6-2 @Component를 이용한 스프링 컴포넌트 지정......................................................................................................239

6-3 @Autowired - 형식을 기준으로 한 의존성 자동 연결............................................................................................243

6-4 @Qualifier - 이름을 기준으로 한 의존성 자동 연결................................................................................................248

6-5 JSR 330의 @Inject 및 @Named 어노테이션..........................................................................................................250

6-6 JSR 250의 @Resource 어노테이션...........................................................................................................................252

6-7 @Scope, @Lazy, @DependsOn, @Primary 어노테이션......................................................................................253

6-8 @Value 어노테이션을 이용한 컴포넌트 구성 간소화.............................................................................................255

6-9 스프링 Validator 인터페이스를 이용한 객체의 유효성 검사..................................................................................261

6-10 JSR 303 어노테이션을 이용한 제약 조건 지정......................................................................................................266

스프링의.JSR.303.지원..............................................................................................................................................268

6-11 @Configuration 및 @Bean 어노테이션을 이용한 프로그래밍 방식의 스프링 빈 구성..................................271

6-12 요약..............................................................................................................................................................................276

IX

목 차

07. 스프링을 이용한 데이터베이스와의 상호작용

7-1 소개................................................................................................................................................................................277

7-2 MyBank 애플리케이션의 요구사항...........................................................................................................................278

7-3 스프링의 JDBC 모듈을 활용한 MyBank 애플리케이션 개발.................................................................................279

데이터.원본.구성.........................................................................................................................................................279

스프링의.JDBC.모듈.클래스를.사용하는.DAO.작성............................................................................................281

7-4 하이버네이트를 이용한 MyBank 애플리케이션 개발.............................................................................................290

SessionFactory.인스턴스.구성................................................................................................................................291

하이버네이트.API를.이용해.데이터베이스.상호작용을.수행하는.DAO.작성..................................................292

7-5 스프링을 이용한 트랜잭션 관리.................................................................................................................................294

MyBank의.트랜잭션.관리.요구사항........................................................................................................................294

프로그래밍.방식의.트랜잭션.관리............................................................................................................................295

선언식.트랜잭션.관리.................................................................................................................................................300

스프링의.JTA.지원......................................................................................................................................................304

7-6 요약................................................................................................................................................................................306

08. 스프링을 이용한 메시징, 이메일 전송, 비동기 메시지 실행 및 캐싱

8-1 소개................................................................................................................................................................................307

8-2 MyBank 애플리케이션의 요구사항...........................................................................................................................307

8-3 JMS 메시지 전송..........................................................................................................................................................309

ActiveMQ.브로커를.임베디드.모드로.실행하도록.구성.....................................................................................309

JMS.ConnectionFactory.구성................................................................................................................................310

JmsTemplate을.이용한.JMS.메시지.전송.............................................................................................................311

단일.트랜잭션.내에서.JMS.메시지.전송.................................................................................................................313

동적.JMS.대상.및.JmsTemplate.구성....................................................................................................................318

JmsTemplate과.메시지.변환...................................................................................................................................319

X

목 차

8-4 JMS 메시지 수신..........................................................................................................................................................320

JmsTemplate을.이용해.동기식으로.JMS.메시지.수신하기...............................................................................320

메시지.수신자.컨테이너를.이용해.비동기식으로.JMS.메시지.수신하기..........................................................321

8-5 이메일 전송...................................................................................................................................................................324

8-6 작업 예약 및 비동기 실행............................................................................................................................................331

TaskExecutor.인터페이스........................................................................................................................................332

TaskScheduler.인터페이스......................................................................................................................................334

@Async.및.@Scheduled.어노테이션....................................................................................................................337

8-7 캐싱................................................................................................................................................................................339

CacheManager.구성................................................................................................................................................341

캐싱.어노테이션.-.@Cacheable,.@CacheEvict,.@CachePut.........................................................................342

@Cacheable................................................................................................................................................................343

8-8 MyBank 애플리케이션 실행.......................................................................................................................................346

8-9 요약................................................................................................................................................................................349

09. 관점 지향 프로그래밍

9-1 소개................................................................................................................................................................................350

9-2 간단한 AOP 예제.........................................................................................................................................................350

9-3 스프링 AOP 프레임워크..............................................................................................................................................354

프록시.생성...................................................................................................................................................................355

expose-proxy.특성....................................................................................................................................................357

9-4 포인트컷 식...................................................................................................................................................................359

@Pointcut.어노테이션..............................................................................................................................................360

execution.및.args.포인트컷.지정자.......................................................................................................................361

bean.포인트컷.지정자...............................................................................................................................................365

어노테이션.기반.포인트컷.지정자............................................................................................................................366

XI

목 차

9-5 어드바이스 유형...........................................................................................................................................................368

사전.어드바이스...........................................................................................................................................................368

반환.후.어드바이스.....................................................................................................................................................368

예외.후.어드바이스.....................................................................................................................................................370

사후.어드바이스...........................................................................................................................................................371

전후.어드바이스...........................................................................................................................................................372

9-6 스프링 AOP - XML 스키마 스타일............................................................................................................................374

AOP.관점의.구성........................................................................................................................................................375

어드바이스.구성...........................................................................................................................................................376

반환.후.어드바이스.구성............................................................................................................................................376

포인트컷.식과.어드바이스.연결................................................................................................................................378

9-7 요약................................................................................................................................................................................379

10. 스프링 웹 MVC 기초

10-1 소개..............................................................................................................................................................................380

10-2 샘플 웹 프로젝트의 디렉터리 구조..........................................................................................................................381

10-3 ‘Hello World’ 웹 애플리케이션의 이해...................................................................................................................382

HelloWorldController.java.-.Hello.World.웹.애플리케이션의.컨트롤러.클래스.......................................382

helloworld.jsp.-.‘Hello.World.!!’.메시지를.보여주는.JSP.페이지..................................................................384

myapp-config.xml.-.웹.애플리케이션.컨텍스트.XML.파일.............................................................................385

web.xml.-.웹.애플리케이션.배포.설명자...............................................................................................................387

10-4 DispatcherServlet - 프런트 컨트롤러.....................................................................................................................390

ServletContext.및.ServletConfig.객체.접근.......................................................................................................392

10-5 @Controller 및 @RequestMapping 어노테이션을 이용한 컨트롤러 개발......................................................394

어노테이션이.지정된.컨트롤러를.활용한.‘Hello.World’.웹.애플리케이션.개발.............................................394

@Controller.및.@RequestMapping.어노테이션...............................................................................................394

스프링.웹.MVC.어노테이션.활성화.........................................................................................................................397

XII

목 차

10-6 MyBank 웹 애플리케이션의 요구사항...................................................................................................................398

10-7 스프링 MVC 어노테이션 - @RequestMapping 및 @RequestParam..............................................................399

@RequestMapping을.이용해.요청을.컨트롤러.또는.컨트롤러.메서드로.연결하기....................................399

@RequestMapping.어노테이션이.지정된.메서드의.인자.................................................................................407

@RequestMapping.어노테이션이.지정된.메서드의.반환.형식.......................................................................408

@RequestParam을.이용해.요청.매개변수를.컨트롤러.메서드로.전달하기...................................................410

모든.요청.매개변수를.컨트롤러.메서드로.전달.....................................................................................................412

value.특성을.이용한.요청.매개변수의.이름.지정.................................................................................................414

required.특성을.이용한.요청.매개변수의.필수.여부.지정..................................................................................414

defaultValue.특성을.이용한.요청.매개변수의.기본값.지정..............................................................................414

10-8 유효성 검사.................................................................................................................................................................415

10-9 @ExceptionHandler 어노테이션을 이용한 예외 처리.........................................................................................419

10-10 루트 웹 애플리케이션 컨텍스트 XML 파일 로딩................................................................................................422

10-11 요약...........................................................................................................................................................................423

11. 스프링 웹 MVC에서의 유효성 검사 및 데이터 바인딩

11-1 소개..............................................................................................................................................................................424

11-2 @ModelAttribute 특성으로 모델 특성 추가 및 검색...........................................................................................425

메서드.단계의.@ModelAttribute.어노테이션을.이용한.모델.특성.추가........................................................425

@ModelAttribute.어노테이션을.이용해.모델.특성.가져오기..........................................................................431

요청.처리와.@ModelAttribute.어노테이션이.지정된.메서드..........................................................................434

@ModelAttribute.어노테이션이.지정된.메서드.인자의.동작.방식.................................................................435

RequestToViewNameTranslator..........................................................................................................................436

11-3 @SessionAttributes 어노테이션으로 모델 특성 캐싱하기..................................................................................437

11-4 스프링에서의 데이터 바인딩....................................................................................................................................442

WebDataBinder.-.웹.요청.매개변수를.위한.데이터.바인더..............................................................................444

XIII

목 차

WebDataBinder.인스턴스.구성..............................................................................................................................446

@ControllerAdvice.어노테이션이.지정된.클래스에서.@InitBinder.

어노테이션이.지정된.메서드.정의하기....................................................................................................................451

데이터.바인딩.프로세스에.필드.포함/제외.............................................................................................................452

BindingResult.객체를.이용한.데이터.바인딩.및.유효성.검사의.오류.조사.....................................................455

11-5 스프링의 유효성 검사 지원.......................................................................................................................................457

스프링.Validator.인터페이스를.이용한.모델.특성의.유효성.검사....................................................................458

JSR.303.어노테이션을.이용한.제약.조건.지정......................................................................................................463

JSR.303.어노테이션을.이용한.객체의.유효성.검사.............................................................................................465

JSR.303의.@Valid.어노테이션을.이용한.모델.특성의.유효성.검사.................................................................467

11-6 스프링 form 태그 라이브러리..................................................................................................................................468

스프링.form.태그.라이브러리의.HTML5.지원.....................................................................................................472

11-7 요약..............................................................................................................................................................................472

12. 스프링 웹 MVC를 이용한 RESTful 웹 서비스 개발

12-1 소개..............................................................................................................................................................................473

12-2 정기 예금 웹 서비스...................................................................................................................................................474

12-3 스프링 웹 MVC를 이용한 RESTful 웹 서비스 구현...............................................................................................475

JSON(JavaScript.Object.Notation)....................................................................................................................477

FixedDepositWS.웹.서비스.구현............................................................................................................................478

12-4 RestTemplate을 이용한 RESTful 웹 서비스 접근.................................................................................................487

12-5 HttpMessageConverter를 이용한 자바 객체 및 HTTP 요청/응답 간 변환.......................................................499

12-6 @PathVariable 및 @MatrixVariable 어노테이션.................................................................................................500

12-7 요약..............................................................................................................................................................................505

XIV

목 차

13. 스프링 웹 MVC 활용 - 국제화, 파일 업로드 및 비동기 요청 처리

13-1 소개..............................................................................................................................................................................506

13-2 핸들러 인터셉터를 통한 요청의 사전 및 사후 처리...............................................................................................507

핸들러.인터셉터.구현.및.구성...................................................................................................................................507

13-3 리소스 번들을 이용한 국제화...................................................................................................................................510

MyBank.웹.애플리케이션의.요구사항....................................................................................................................510

MyBank.웹.애플리케이션의.국제화.및.지역화.....................................................................................................511

13-4 비동기식 요청 처리....................................................................................................................................................514

비동기.요청.처리.구성................................................................................................................................................514

Callable을.반환하는.@RequestMapping.어노테이션이.지정된.메서드.......................................................515

DeferredResult를.반환하는.@RequestMapping.어노테이션이.지정된.메서드.........................................516

DeferredResult.인스턴스의.결과.계산..................................................................................................................520

기본.시간.제한.값.설정...............................................................................................................................................525

비동기.요청.가로채기.................................................................................................................................................526

13-5 스프링의 형변환 및 서식 지정 지원.........................................................................................................................527

사용자.지정.변환기.만들기........................................................................................................................................527

사용자.지정.변환기.구성.및.사용.............................................................................................................................528

사용자.지정.포매터.만들기........................................................................................................................................531

사용자.지정.포매터.구성............................................................................................................................................532

AnnotationFormatterFactory를.생성해.@AmountFormat.어노테이션이.지정된.필드에만

서식.지정하기...............................................................................................................................................................533

AnnotationFormatterFactory.구현.구성.............................................................................................................535

13-6 스프링 웹 MVC의 파일 업로드 지원.......................................................................................................................536

CommonsMultipartResolver를.이용한.파일.업로드........................................................................................537

StandardServletMultipartResolver를.이용한.파일.업로드.............................................................................540

13-7 요약..............................................................................................................................................................................541

목 차

14. 스프링 시큐리티를 이용한 애플리케이션의 보안 구현

14-1 소개..............................................................................................................................................................................542

14-2 MyBank 웹 애플리케이션의 보안 요구사항..........................................................................................................542

14-3 스프링 시큐리티를 이용한 MyBank 웹 애플리케이션의 보안 구현....................................................................544

웹.요청.보안.구성........................................................................................................................................................545

인증.구성.......................................................................................................................................................................548

스프링.시큐리티의.JSP.태그.라이브러리를.이용한.JSP.콘텐츠.보호................................................................550

메서드.보호...................................................................................................................................................................552

14-4 MyBank 웹 애플리케이션 - 스프링 시큐리티의 ACL 모듈을 이용한 FixedDepositDetails 인스턴스 보호.......556

ch14-bankapp-db-security.프로젝트.배포.및.사용..........................................................................................556

ACL과.사용자.정보를.저장하는.데이터베이스.테이블.........................................................................................559

사용자.인증...................................................................................................................................................................564

웹.요청.보안.................................................................................................................................................................566

JdbcMutableAclService.구성.................................................................................................................................568

메서드.단계.보안.구성................................................................................................................................................571

도메인.객체.인스턴스.보안........................................................................................................................................573

프로그래밍.방식의.ACL.항목.관리..........................................................................................................................576

MutableAcl과.보안....................................................................................................................................................580

14-5 요약..............................................................................................................................................................................581

부록 A. 이클립스 IDE(또는 인텔리제이 IDEA)로 샘플 프로젝트 가져오기 및 배포

A-1 개발 환경 설정..............................................................................................................................................................582

A-2 이클립스 IDE(또는 인텔리제이 IDEA)로 샘플 프로젝트 가져오기.......................................................................583

샘플.프로젝트.가져오기.............................................................................................................................................583

이클립스.IDE에서.M2_REPO.클래스.경로.변수.구성.........................................................................................585

A-3 톰캣 7 서버와 함께 작동하도록 이클립스 IDE 구성하기........................................................................................585

A-4 톰캣 7 서버로 웹 프로젝트 배포하기........................................................................................................................587

임베디드.모드에서.톰캣.7.서버.실행.......................................................................................................................588

XVI

이 책을 활용하는 방법

샘플 프로젝트 다운로드

이 책에서 다루는 샘플 프로젝트는 구글 코드 프로젝트(http://code.google.com/p/getting-

started-with-spring-framework-2edition/)에서 다운로드할 수 있다. 샘플 프로젝트는 각각의

ZIP 파일로 다운로드하거나 SVN으로 체크아웃할 수 있다. 자세한 내용은 위쪽의 URL을 참조한다.

샘플 프로젝트를 이클립스 IDE 또는 인텔리제이 IDEA로 가져오기

이 책을 읽는 동안 예제 프로젝트:장<장 번호>/<프로젝트 이름>이라는 표시가 나오면 해당 프로젝트를

이클립스 IDE 또는 인텔리제이 IDEA (또는 사용 중인 다른 IDE )로 가져와야 한다. 메이븐 3.x 빌드 툴

로 샘플 프로젝트를 빌드했으므로 각 프로젝트 안에 pom.xml 파일이 있으며, 소스코드 배포판의 루트

에도 전체 프로젝트를 빌드하는 pom.xml 파일이 있다.

샘플 프로젝트를 가져오고 실행하는 단계는 부록 A를 참고한다.

코드 예제 참조

각 예제에는 샘플 프로젝트 이름과 소스 파일의 위치가 나온다. 프로젝트와 소스 위치 레이블이 없는 예

제 코드는 샘플 프로젝트에 포함되는 코드가 아니라 순수하게 설명을 위해 작성된 것이다.

이 책에 사용되는 관례

용어 강조는 용어를 강조한다.

코드 내용은 예제와 자바 코드, 그리고 XML과 속성 파일의 구성 내역을 표시한다.

코드 내용 강조는 예제에 사용되며 소스 또는 구성에서 중요한 부분을 강조한다.

텍스트 상자는 중요한 요점이나 개념을 강조한다.

서문

XVII

의견 및 질문

다음의 구글 그룹스 포럼에서 의견이나 질문을 저자에게 보낼 수 있다.

■ https://groups.google.com/forum/#!forum/getting-started-with-spring-framework

저자 소개

애쉬쉬 사린(Ashish Sarin )은 애플리케이션 설계 분야에서 14년 이상의 경험을 보유한 썬 인증 엔터프

라이즈 설계자다. 저서로 Spring Roo 1.1 Cookbook (팩트 출판사)과 Portlets in Action (매닝 출판

사)이 있다.

제이 샤마(J Sharma )는 스프링 애플리케이션 개발에 대한 광범위한 경험을 갖춘 프리랜서 자바 개발자

다.

서문

18 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

1-1 소개

기존의 자바 엔터프라이즈 애플리케이션 개발 프로젝트에서는 애플리케이션을 구조적이고, 관리하거나

테스트하기 쉽게 만드는 책임이 개발자에게 있었다. 개발자는 애플리케이션의 이러한 비즈니스와 무관

한 요건을 충족하기 위해 수많은 디자인 패턴을 사용해야 했다. 이러한 부담 요소는 개발자의 생산성은

물론 개발된 애플리케이션의 품질에도 좋지 않은 영향을 미쳤다.

스프링 프레임워크(또는 줄여서 ‘스프링’)는 스프링소스(http://www.springsource.org )라는 단체

에서 애플리케이션 개발을 간소화하기 위해 개발한 오픈소스 애플리케이션 프레임워크다. 스프링 프레

임워크는 구조적이고, 관리가 용이하며, 테스트하기 쉬운 애플리케이션을 개발하기 위한 인프라를 제공

하며, 개발자가 애플리케이션의 비즈니스 논리를 작성하는 데만 집중할 수 있게 함으로써 개발자의 생산

성을 높여준다. 스프링 프레임워크는 독립형 애플리케이션은 물론 웹 애플리케이션, 애플릿 또는 다른

모든 유형의 자바 애플리케이션을 개발하는 데 사용할 수 있다.

1장에서는 스프링 프레임워크 모듈과 그 장점을 소개하면서 시작한다. 스프링 프레임워크의 핵심에

는 의존성 주입(DI; Dependency Injection )이라는 기능을 제공하는 제어 반전(IoC; Inversion of

Control ) 컨테이너가 있다. 1장에서는 스프링의 의존성 주입 기능과 제어 반전 컨테이너를 소개하고,

스프링 프레임워크 소개

01

01. 스프링 프레임워크 소개 19

스프링을 사용해 독립형 자바 애플리케이션을 개발하는 과정을 설명한다. 그리고 뒷부분에서는 스프링

소스에서 스프링 프레임워크를 기반으로 개발한 몇 가지 프로젝트를 설명한다. 1장은 이후 장에서 스프

링 프레임워크를 좀 더 심층적으로 다루기 위한 기본 정보를 제공한다.

이 책에서는 스프링 프레임워크의 기능을 소개하기 위해 MyBank라는 인터넷 뱅킹 애플리케이션을 예제로 사용한다.

1-2 스프링 프레임워크 모듈

스프링 프레임워크는 지원하는 애플리케이션 개발 기능을 기준으로 그룹화된 여러 모듈로 구성돼 있다.

스프링 프레임워크의 여러 모듈 그룹에 대해서는 다음 표를 참고한다.

모듈 그룹 설명

코어 컨테이너 스프링 프레임워크의 기본 모듈을 포함한다. 이 그룹의 모듈은 스프링의 DI 기능과 IoC 컨테이너 구

현을 제공한다.

AOP 및 인스트루먼테이션 관점 지향 프로그래밍(AOP; Aspect-Oriented Programming) 및 클래스 인스트루먼테이션(class

instrumentation)을 지원하는 모듈을 포함한다.

데이터 접근/통합 데이터베이스 및 메시징 공급자와의 상호작용을 간소화하는 모듈을 포함한다. 이 모듈 그룹은 프로

그래밍 방식 및 선언식 트랜잭션 관리와 객체/XML 매핑 구현(예: JAXB 및 캐스터)을 지원하는 모듈

도 포함한다.

웹 웹 및 포틀릿 애플리케이션 개발을 간소화하는 모듈을 포함한다.

테스트 단위 및 통합 테스트 생성을 간소화하는 모듈 하나를 포함한다.

이 표를 보면 스프링이 엔터프라이즈 애플리케이션 개발의 모든 측면을 지원한다는 점을 알 수 있다. 즉,

스프링으로 웹 애플리케이션 개발, 데이터베이스 접근, 트랜잭션 관리, 단위 및 통합 테스트 생성을 비롯

한 모든 작업을 할 수 있다. 스프링 프레임워크 모듈은 애플리케이션에 필요한 모듈만 포함할 수 있도록

설계돼 있다. 예를 들어, 애플리케이션에서 스프링의 DI 기능을 사용하려면 코어 컨테이너 그룹에 속한

모듈만 포함하면 된다. 이 책을 진행하면서 스프링의 여러 모듈에 대해 자세히 알아보고 애플리케이션

개발에 이를 사용하는 방법을 설명하겠다.

다음 그림은 스프링의 모듈 간 상호의존성을 보여준다.

20 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

데이터 접근/통합

테스트

코어 컨테이너AOP 및 인스트루먼테이션

의존

의존

의존

의존

의존

의존

그림 1-1 스프링 모듈의 상호의존성

이 그림을 보면 코어 컨테이너 그룹이 스프링 프레임워크의 중심에 있고 다른 모듈이 이에 의존한다는

것을 알 수 있다. AOP 및 인스트루먼테이션 그룹에 포함된 모듈도 스프링 프레임워크의 다른 모듈에

AOP 기능을 제공하므로 중요도가 높다.

지금까지 스프링으로 처리할 수 있는 애플리케이션 개발 영역의 기본 개념을 알아봤다. 이어서 스프링

IoC 컨테이너에 대해 알아보자.

1-3 스프링 IoC 컨테이너

자바 애플리케이션은 상호작용을 통해 애플리케이션 동작을 제공하는 객체로 구성된다. 객체가 상호작

용하는 대상 객체를 객체의 의존성(dependency )이라고 한다. 예를 들어, 객체 X가 객체 Y 및 Z와 상

호작용하는 경우 Y 및 Z는 객체 X의 의존성이다. DI는 객체의 의존성을 일반적으로 세터 메서드 및 객

체 생성자의 인자를 통해 지정하는 디자인 패턴이다. 이러한 의존성은 객체가 생성될 때 객체로 주입된

다.

스프링 애플리케이션에서는 IoC 컨테이너(또는 스프링 컨테이너라고도 한다)가 애플리케이션 객체를

생성하고 그 의존성을 주입하는 역할을 한다. 스프링 컨테이너가 생성하고 관리하는 애플리케이션 객체

를 빈(bean )이라고 한다. 애플리케이션 객체를 구성하는 역할을 스프링 컨테이너가 수행하므로 개발자

는 팩터리, 서비스 로케이터 등의 디자인 패턴을 직접 구현하지 않고도 애플리케이션을 개발할 수 있다.

01. 스프링 프레임워크 소개 21

DI는 제어 반전(IoC, Inversion of Control )이라고도 하는데, 의존성을 생성하고 주입하는 역할을

애플리케이션 객체가 아닌 스프링 컨테이너가 수행하기 때문이다.

예를 들어, 우리가 사용할 샘플 애플리케이션인 MyBank에 FixedDepositController와 Fixed

DepositService라는 객체 두 개가 포함돼 있다고 해보자. 다음 예제를 보면 FixedDepositController

객체가 FixedDepositService 객체에 의존한다는 것을 알 수 있다.

예제 1-1: FixedDepositController 클래스

public class FixedDepositController {

private FixedDepositService fixedDepositService;

public FixedDepositController() {

fixedDepositService = new FixedDepositService();

}

public boolean submit() {

//-- 정기 예금 내역 저장

fixedDepositService.save(.....);

}

}

이 예제에서 FixedDepositController의 생성자는 나중에 FixedDepositController의 submit

메서드에서 사용하기 위해 FixedDepositService의 인스턴스를 생성한다. 여기서 Fixed

DepositController는 FixedDepositService와 상호작용하므로 FixedDepositService는

FixedDepositController의 의존성이다.

FixedDepositController를 스프링 빈으로 구성하려면 예제 1-1의 FixedDepositController 클래스

를 수정해서 FixedDepositService 의존성을 생성자 인자나 세터 메서드의 인자로 받게 해야 한다. 다

음 예제는 수정된 FixedDepositController 클래스다.

예제 1-2: FixedDepositController 클래스 - FixedDepositService가 생성자 인자로 전달된다.

public class FixedDepositController {

private FixedDepositService fixedDepositService;

22 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

public FixedDepositController(FixedDepositService fixedDepositService) {

this.fixedDepositService = fixedDepositService;

}

public boolean submit() {

//-- 정기 예금 내역 저장

fixedDepositService.save(.....);

}

}

이 예제에서는 FixedDepositService 인스턴스를 생성자 인자를 통해 FixedDepositController 인

스턴스로 전달했다. 이제 FixedDepositService 클래스를 스프링 빈으로 구성할 수 있다. 참고로

FixedDepositController 클래스는 스프링 인터페이스나 클래스를 구현하거나 확장하지 않는다.

애플리케이션 객체와 그 의존성에 대한 정보는 구성 메타데이터를 이용해 지정한다. 스프링 IoC 컨테이

너는 애플리케이션의 구성 메타데이터를 읽고 이를 바탕으로 애플리케이션 객체를 인스턴스화하고 그

의존성을 주입한다. 다음 예제에는 MyController와 MyService 클래스로 구성된 애플리케이션의 구성

메타데이터(XML 형식)가 나온다.

예제 1-3: 구성 메타데이터

<beans .....>

<bean id="myController" class="sample.spring.controller.MyController">

<constructor-arg index="0" ref="myService" />

</bean>

<bean id="myService" class="sample.spring.service.MyService"/>

</beans>

이 예제에서 각 <bean> 요소에는 스프링 컨테이너가 관리할 애플리케이션 객체를 정의하며,

<constructor-arg> 요소에는 MyService의 인스턴스가 MyController의 생성자 인자로 전달된다는

것을 지정한다. <bean> 요소에 대해서는 1장의 뒷부분에서 자세히 설명하며, <constructor-arg> 요

소에 대해서는 2장에서 설명한다.

01. 스프링 프레임워크 소개 23

스프링 컨테이너는 예제 1-3과 같은 애플리케이션의 구성 메타데이터를 읽고 이 정보를 바탕으로

<bean> 요소로 정의된 애플리케이션 객체를 생성하고 그 의존성을 주입한다. 스프링 컨테이너는 애플

리케이션 객체를 생성하고 그 의존성을 주입하기 위해 자바 리플렉션 API1를 사용한다. 다음 그림은 스

프링 컨테이너가 작동하는 방법을 간단하게 보여준다.

스프링 컨테이너가 자바 리플렉션 API를

이용해 애플리케이션 객체를 생성하고 그

의존성을 주입한다.

읽기

XML, 어노테이션 또는 자바 코드를

통해 지정된 구성 메타데이터

스프링 컨테이너 생성

애플리케이션 객체

애플리케이션

그림 1-2 스프링 컨테이너는 애플리케이션의 구성 메타데이터를 읽고 구성이 완료된 애플리케이션을 생성한다.

구성 메타데이터를 스프링 컨테이너로 제공하는 방법에는 XML (예제 1-3에 나온 것과 같음)이나 자바

어노테이션을 사용하는 방법(6장 참조), 그리고 자바 코드를 통한 방법(6장 참조)이 있다.

스프링 컨테이너는 애플리케이션 객체를 생성하고 관리하는 역할을 담당하는 것은 물론 엔터프라이즈

서비스(예: 트랜잭션 관리, 보안, 원격 접근 등)를 투명하게 객체에 적용하는 기능도 제공한다. 스프

링 컨테이너가 이러한 추가 기능으로 애플리케이션 객체를 보완하므로 애플리케이션 객체를 단순 자바

객체(POJO; Plain Old Java Object )로 모델링할 수 있게 된다. POJO에 해당하는 자바 클래스를

POJO 클래스라고 하는데, 간단하게 말해 프레임워크 인터페이스나 클래스를 구현하거나 확장하지 않

는 자바 클래스를 의미한다. POJO에 필요한 트랜잭션 관리, 보안, 원격 접근 등의 엔터프라이즈 서비스

는 스프링 컨테이너가 내부적으로 제공한다.

지금까지 스프링 컨테이너가 작동하는 방법을 알아봤다. 다음으로 스프링을 이용해 애플리케이션을 개

발할 때의 장점을 몇 가지 예를 통해 확인해보자.

1  http://docs.oracle.com/javase/tutorial/reflect/index.html

1-4 스프링 프레임워크의 장점

이전 절에서 스프링의 장점을 다음과 같이 설명했다.

■ 스프링은 애플리케이션 객체를 생성하고 그 의존성을 주입하는 역할을 대신해 자바 애플리케이션을 간단하게 개발하게

끔 돕는다.

■ 스프링은 애플리케이션을 POJO로 개발하게끔 돕는다.

스프링은 기본 구성 코드를 처리하는 추상화 계층도 제공하므로 JMS 공급자, JNDI, MBean 서버, 이메

일 서버, 데이터베이스 등과의 상호작용을 간단하게 처리할 수 있다.

스프링을 이용해 애플리케이션을 개발할 때의 장점을 잘 이해할 수 있는 몇 가지 예를 간단하게 살펴보자.

로컬 및 전역 트랜잭션을 일관된 방법으로 관리

스프링을 이용해 트랜잭션 애플리케이션을 개발하는 경우 스프링의 선언식 트랜잭션 관리 기능으로 트

랜잭션을 관리할 수 있다.

다음 예제는 MyBank 애플리케이션의 FixedDepositService 클래스다.

예제 1-4: FixedDepositService 클래스

public class FixedDepositService {

public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) { ..... }

}

FixedDepositService 클래스는 정기 예금 내역을 생성하고 검색하는 메서드를 정의하는 POJO 클래

스다. 다음 그림은 정기 예금을 개설하는 양식을 보여준다.

그림 1-3 정기 예금을 개설하는 HTML 양식

01. 스프링 프레임워크 소개 25

고객이 이 양식에 정기 예금 금액(Deposit Amount ), 기간(Tenure ), 이메일(Email ) 정보

를 입력하고 저장(Save ) 버튼을 클릭하면 정기 예금이 새로 생성된다. 그러면 정기 예금을 생성

하기 위해 FixedDepositService의 createFixedDeposit 메서드(예제 1-1 참조)가 호출된다.

createFixedDeposit 메서드는 고객의 은행 계좌에서 고객이 입력한 금액을 인출하고 동일한 금액으로

정기 예금을 생성한다.

고객의 은행 잔고 정보는 BANK_ACCOUNT_DETAILS 데이터베이스 테이블에 저장되고, 정기 예금

내역은 FIXED_DEPOSIT_DETAILS 데이터베이스 테이블에 저장된다고 가정해보자. 고객이 금액이 x

인 정기 예금을 만든 경우 BANK_ACCOUNT_DETAILS 테이블에서 x를 빼고, FIXED_DEPOSIT_

DETAILS 테이블에 같은 금액의 정기 예금을 포함하는 레코드를 삽입해야 한다. BANK_ACCOUNT_

DETAILS 테이블을 업데이트하지 않거나 FIXED_DEPOSIT_DETAILS 테이블에 새 레코드를 삽입하

지 않으면 시스템이 일관되지 않은 상태가 된다. 다시 말해, createFixedDeposit 메서드는 한 트랜잭

션 안에서 실행해야 한다.

MyBank 애플리케이션에서 사용하는 데이터베이스처럼 트랜잭션의 대상이 되는 리소스를 트랜잭션 리

소스라고 한다. 데이터베이스 수정 작업 집합을 단일 작업 단위로 수행하는 기존 방식을 사용하는 경우

먼저 JDBC 연결의 자동 커밋 모드를 비활성화하고, SQL 문을 실행한 다음, 마지막으로 트랜잭션을 커

밋(또는 롤백)해야 한다. 다음 예제에는 createFixedDeposit 메서드에서 기존 방식으로 데이터베이스

트랜잭션을 관리하는 방법이 나온다.

예제 1-5: JDBC Connection 객체를 사용해 프로그래밍 방식으로 데이터베이스 트랜잭션 관리

import java.sql.Connection;

import java.sql.SQLException;

public class FixedDepositService {

public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) {

Connection con = ..... ;

try {

con.setAutoCommit(false);

//-- 데이터베이스 테이블을 수정하는 SQL 문 실행

con.commit();

} catch(SQLException sqle) {

26 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

if(con != null) {

con.rollback();

}

}

.....

}

}

이 예제에서 createFixedDeposit 메서드는 JDBC Connection 객체를 사용해 프로그래밍 방식으로

데이터베이스 트랜잭션을 관리한다. 이 방식은 단일 데이터베이스를 사용하는 애플리케이션에 적합하

다. JDBC Connection을 사용하는 트랜잭션과 같이 특정 리소스에 한정된 트랜잭션을 로컬 트랜잭션

이라고 한다.

반면 여러 트랜잭션 리소스가 사용되는 경우 JTA (Java Transaction API )를 사용해 트랜잭션을 관리

해야 한다. 예를 들어, 동일한 트랜잭션 내에서 JMS 메시지를 메시징 미들웨어(한 트랜잭션 리소스)로

전송하고 데이터베이스(다른 트랜잭션 리소스)를 업데이트하려는 경우 JTA 트랜잭션 관리자를 사용해

트랜잭션을 관리해야 한다. JTA 트랜잭션은 전역 트랜잭션(또는 분산 트랜잭션)이라고도 한다. JTA를

사용하려면 JNDI에서 UserTransaction 객체(JTA API에 포함됨)를 가져온 다음 프로그래밍 방식으

로 트랜잭션을 시작 및 커밋(또는 롤백)해야 한다.

이와 같이 JDBC Connection (로컬 트랜잭션의 경우)이나 UserTransaction (전역 트랜잭션의 경우)

객체를 사용해 프로그래밍 방식으로 트랜잭션을 관리할 수 있다. 다만, 로컬 트랜잭션은 전역 트랜잭션

내에서 실행할 수 없다는 데 주의해야 한다. 즉, createFixedDeposit 메서드(예제 1-5 참조)에서 수

행하는 데이터베이스 업데이트를 JTA 트랜잭션에 포함시키려면 UserTransaction 객체로 트랜잭션을

관리하도록 createFixedDeposit 메서드를 수정해야 한다.

스프링은 로컬 및 전역 트랜잭션을 일관된 방법으로 관리하는 추상화 계층을 제공함으로써 트랜잭션 관

리를 간소화한다. 즉, 스프링의 트랜잭션 추상화를 사용해 createFixedDeposit 메서드(예제 1-5 참

조)를 작성하면 로컬에서 전역 트랜잭션 관리로 전환하거나 그 반대로 전환할 때 메서드를 수정할 필요

가 없다. 스프링의 트랜잭션 추상화는 7장에서 설명한다.

01. 스프링 프레임워크 소개 27

선언식 트랜잭션 관리

스프링에서는 선언식으로 트랜잭션을 관리할 수 있다. 다음과 같이 스프링 @Transactional 어노테이

션을 지정하면 스프링이 트랜잭션을 처리한다.

예제 1-6: @Transactional 어노테이션 사용

import org.springframework.transaction.annotation.Transactional;

public class FixedDepositService {

public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

@Transactional

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) { ..... }

}

이 예제에서 FixedDepositService 클래스는 스프링 관련 인터페이스나 클래스를 구현하거나 확장하

지 않고도 스프링의 트랜잭션 관리 기능을 사용하고 있다. 스프링 프레임워크는 @Transactional 어노

테이션이 지정된 createFixedDeposit 메서드에 자연스럽게 트랜잭션 관리 기능을 제공한다. 즉, 스프

링은 애플리케이션 객체가 스프링 관련 클래스나 인터페이스에 의존하도록 강요하지 않는다. 또한 트랜

잭션을 관리하기 위해 트랜잭션 관리 API를 직접 사용할 필요도 없다.

보안

보안은 모든 자바 애플리케이션에서 중요한 측면이다. 스프링소스에서는 스프링 프레임워크를 기반으로

하는 스프링 시큐리티(Spring Security, http://static.springsource.org/spring-security/site/)라

는 프레임워크를 제공한다. 스프링 시큐리티는 자바 애플리케이션에서 보안을 구현하기 위한 인증 및 권

한 부여 기능을 제공한다.

MyBank 애플리케이션에 사용할 LOAN_CUSTOMER, SAVINGS_ACCOUNT_CUSTOMER,

APPLICATION_ADMIN이라는 사용자 역할 3개가 있다고 가정해보자. FixedDepositService 클

래스(예제 1-6 )의 createFixedDeposit 메서드를 호출하려면 고객에게 SAVINGS_ACCOUNT_

CUSTOMER 또는 APPLICATION_ADMIN 역할이 있어야 한다. 스프링 시큐리티를 사용하면 다음

예제와 같이 createFixedDeposit 메서드에 스프링 시큐리티의 @Secured 어노테이션을 지정해 이 문

제를 간단하게 해결할 수 있다.

28 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

예제 1-7: 보안이 적용된 createFixedDeposit 메서드

import org.springframework.transaction.annotation.Transactional;

import org.springframework.security.access.annotation.Secured;

public class FixedDepositService {

public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

@Transactional

@Secured({ "SAVINGS_ACCOUNT_CUSTOMER", "APPLICATION_ADMIN" })

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) { ..... }

}

메서드에 스프링 시큐리티의 @Secured 어노테이션을 지정하면 스프링 시큐리티 프레임워크가 자연스

럽게 메서드에 보안 기능을 적용한다. 이 예제를 보면 스프링 전용 클래스나 인터페이스를 확장하거나

구현하지 않고도 메서드 단계에서 보안을 구현할 수 있음을 알 수 있다. 또한 비즈니스 메서드에 보안 관

련 코드를 넣을 필요도 없다.

스프링 시큐리티 프레임워크는 14장에서 자세히 설명한다.

JMX(Java Management Extensions )

스프링의 JMX 지원을 사용하면 손쉽게 JMX 기술을 애플리케이션에 통합할 수 있다.

MyBank 애플리케이션의 정기 예금 기능을 매일 오전 9:00부터 오후 6:00까지만 제공해야 한

다고 가정해보자. 이렇게 하려면 정기 예금 서비스의 활성화 여부를 나타내는 플래그 역할의 변

수를 FixedDepositService 클래스에 추가해야 한다. 다음 예제는 이러한 플래그를 사용하는

FixedDepositService 클래스다.

예제 1-8: active 변수를 사용하는 FixedDepositService

public class FixedDepositService {

private boolean active;

public FixedDepositDetails getFixedDepositDetails( ..... ) {

if (active) { ..... }

01. 스프링 프레임워크 소개 29

}

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) {

if (active) { ..... }

}

public void activateService() {

active = true;

}

public void deactivateService() {

active = false;

}

}

이 예제에는 active라는 변수가 FixedDepositService 클래스에 추가됐다. active 변수 값이 true인

경우 getFixedDepositDetails 및 createFixedDeposit 메서드가 정상적으로 작동하지만, false인 경

우 getFixedDepositDetails 및 createFixedDeposit 메서드는 현재 정기 예금 서비스를 사용할 수

없음을 나타내는 예외를 생성한다. activateService 및 deactivateService 메서드는 active 변수 값을

각각 true와 false로 설정한다.

그러면 이 activateService 및 deactivateService 메서드는 어디서 호출해야 할까? 이 경우에

는 은행 앱 스케줄러라는 별도의 스케줄러 애플리케이션을 각각 오전 9:00와 오후 6:00에 실행해

activateService 및 deactivateService 메서드를 각각 실행한다고 가정해보자. 은행 앱 스케줄러 애플

리케이션은 FixedDepositService 인스턴스와 원격으로 상호작용하기 위해 JMX (Java Management

Extensions ) API를 사용한다.

JMX에 대한 자세한 내용은 http://docs.oracle.com/javase/tutorial/jmx/index.html을 참고한다.

은행 앱 스케줄러는 JMX를 사용해 FixedDepositService 인스턴스의 active 변수 값을 변경하므

로 FixedDepositService 인스턴스를 MBean 서버에 MBean (Managed Bean )으로 등록하고

FixedDepositService의 activateService 및 deactivateService 메서드를 JMX 작업으로 노출해야

한다. 스프링에서는 클래스에 @ManagedResource 어노테이션을 지정해 클래스 인스턴스를 MBean

서버에 등록하고 @ManagedOperation 어노테이션으로 클래스의 메서드를 JMX 작업으로 노출한다.

30 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

다음 예제에서는 @ManagedResource 어노테이션으로 FixedDepositService 클래스의 인스

턴스를 MBean 서버에 등록하고, @ManagedOperation 어노테이션으로 activateService 및

deactivateService 메서드를 JMX 작업으로 노출했다.

예제 1-9: 스프링의 JMX 지원을 사용하는 FixedDepositService 클래스

import org.springframework.jmx.export.annotation.ManagedOperation;

import org.springframework.jmx.export.annotation.ManagedResource;

@ManagedResource(objectName = "fixed_deposit_service:name=FixedDepositService")

public class FixedDepositService {

private boolean active;

public FixedDepositDetails getFixedDepositDetails( ..... ) {

if (active) { ..... }

}

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) {

if (active) { ..... }

}

@ManagedOperation

public void activateService() {

active = true;

}

@ManagedOperation

public void deactivateService() {

active = false;

}

}

이 예제에서 FixedDepositService 클래스는 JMX API를 직접 사용하지 않고도 인스턴스를 MBean

서버에 등록하고 클래스의 메서드를 JMX 작업으로 노출했다.

01. 스프링 프레임워크 소개 31

JMS(Java Message Service )

스프링의 JMS 지원 기능을 이용하면 JMS 공급자 메시지 전송 및 수신 작업을 손쉽게 처리할 수 있다.

MyBank 애플리케이션에서 고객이 정기 예금 내역을 이메일로 보내달라고 요청하면 Fixed

DepositService가 요청 내역을 JMS 메시징 미들웨어(예: ActiveMQ )로 전송한다. 요청은 이후 메시

지 수신자가 처리한다. 스프링은 JMS 공급자와의 상호작용을 간단하게 처리할 수 있는 추상화 계층을

제공한다. 다음 예제의 FixedDepositService 클래스는 스프링의 JmsTemplate을 사용해 요청 내역

을 JMS 공급자로 전송하는 방법을 보여준다.

예제 1-10: JMS 메시지를 전송하는 FixedDepositService

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.jms.core.JmsTemplate;

public class FixedDepositService {

@Autowired

private transient JmsTemplate jmsTemplate;

.....

public boolean submitRequest(Request request) {

jmsTemplate.convertAndSend(request);

}

}

이 예제에서 FixedDepositService는 JmsTemplate 형식의 변수를 정의하고 스프링의 @Autowired

어노테이션을 지정했다. 짐작할 수 있듯이 @Autowired 어노테이션은 JmsTemplate 인스턴스에 접

근할 수 있게 해주며, JmsTemplate 인스턴스에는 JMS 메시지를 전송할 JMS 대상에 대한 정보가

포함돼 있다. JmsTemplate을 구성하는 방법은 8장에서 자세히 설명한다. FixedDepositService

의 submitRequest 메서드는 JmsTemplate의 convertAndSend 메서드를 호출해 요청 내역

(submitRequest 메서드의 Request 인자로 지정)을 JMS 메시지를 통해 JMS 공급자로 전송한다.

이 경우에도 스프링 프레임워크를 이용해 JMS 공급자로 메시지를 전송하면 JMS API를 직접 다룰 필요

가 없다는 사실을 알 수 있다.

32 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

캐시

스프링은 캐시 추상화를 제공해 애플리케이션에서 일관된 방법으로 캐시를 사용할 수 있게 해준다.

애플리케이션의 성능을 개선하기 위해 캐싱 솔루션을 사용하는 경우가 많은데, MyBank 애플리케이션

의 경우 정기 예금 내역을 읽는 작업의 성능을 개선하기 위해 캐시 기능을 사용한다. 스프링 프레임워크

는 캐시 관련 논리를 추상화해서 다양한 캐싱 솔루션과 손쉽게 상호작용할 수 있게 해준다.

다음 예제에서 FixedDepositService의 getFixedDepositDetails 메서드는 스프링의 캐시 추상화 기

능을 사용해 정기 예금 내역을 캐시한다.

예제 1-11: 정기 예금 내역을 캐시하는 FixedDepositService

import org.springframework.cache.annotation.Cacheable;

public class FixedDepositService {

@Cacheable("FixedDeposits")

public FixedDepositDetails getFixedDepositDetails( ..... ) { ..... }

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) { ..... }

}

이 예제에서 스프링의 @Cacheable 어노테이션은 getFixedDepositDetails 메서드가 반환하는 정기

예금 내역을 캐시하게 한다. 이후 동일한 인자 값으로 getFixedDepositDetails 메서드를 다시 호출하

면 메서드를 다시 실행하지 않고 캐시에 있는 정기 예금 내역을 반환한다. 즉, 스프링 프레임워크를 이용

하면 클래스에 직접 캐시 관련 논리를 추가할 필요가 없다. 스프링의 캐시 추상화는 8장에서 자세히 설

명한다.

이 절에서는 스프링 프레임워크가 POJO에 제공하는 서비스를 사용하면 개발자가 복잡한 저수준 API를

직접 다루지 않고도 간단하게 엔터프라이즈 애플리케이션을 개발할 수 있음을 확인했다. 또한 스프링은

하이버네이트, iBATIS, Quartz, JSF, Struts, EJB 등의 표준 프레임워크와 쉽게 통합할 수 있으므로 엔

터프라이즈 애플리케이션을 개발하는 데 안성맞춤이다.

01. 스프링 프레임워크 소개 33

지금까지 스프링 프레임워크의 주요 이점을 알아봤다. 이어서 간단한 스프링 애플리케이션을 개발하는

방법을 알아보자.

1-5 간단한 스프링 애플리케이션

이 절에서는 스프링의 DI 기능을 사용하는 간단한 스프링 애플리케이션을 소개하겠다. 애플리케이션에

서 스프링의 DI 기능을 사용하려면 다음 단계를 따른다.

1. 애플리케이션 객체와 그 의존성을 확인한다.

2. 1단계에서 확인한 애플리케이션 객체에 해당하는 POJO 클래스를 만든다.

3. 애플리케이션 객체와 그 의존성을 지정하는 구성 메타데이터를 만든다.

4. 스프링 IoC 컨테이너의 인스턴스를 만들고 구성 메타데이터를 전달한다.

5. 스프링 IoC 컨테이너 인스턴스에서 애플리케이션 객체에 접근한다.

이제 MyBank 애플리케이션의 관점에서 이러한 단계를 살펴보자.

애플리케이션 객체와 그것의 의존성 식별하기

앞서 살펴본 MyBank 애플리케이션에서는 정기 예금을 개설하기 위해 사용자에게 양식(그림 1-3 참

조)을 보여준다. 다음 순서도에는 사용자가 이 양식을 제출했을 때 작업을 수행하는 애플리케이션 객체

와 그것의 상호작용이 나온다.

양식 제출

정기 예금 내역 저장

그림 1-4 MyBank의 애플리케이션 객체와 그 의존성

34 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

이 순서도에서 FixedDepositController는 양식을 제출했을 때 요청을 수신하는 웹 컨트롤러

이며, 정기 예금 내역은 FixedDepositDetails 객체에 포함돼 있다. FixedDepositController

는 FixedDepositService (서비스 계층 객체)의 createFixedDeposit 메서드를 호출한다. 그러

면 FixedDepositService가 FixedDepositDao 객체(데이터 접근 객체)를 호출해 정기 예금 내

역을 애플리케이션의 데이터 저장소에 저장한다. 이 순서도를 해석하면 FixedDepositService는

FixedDepositController 객체의 의존성이고, FixedDepositDao는 FixedDepositService 객체의

의존성이다.

예제 프로젝트: chapter 1/ch01-bankapp-xml (이 프로젝트는 스프링의 DI 기능을 사용하는 간단한 스프링 애플리케이

션이다. 이 애플리케이션을 실행하려면 이 프로젝트에서 MyBankApp 클래스의 main 메서드를 실행한다.)

식별한 애플리케이션 객체에 해당하는 POJO 클래스 만들기

애플리케이션 객체를 확인하고 나면 이러한 애플리케이션 객체에 해당하는 POJO 클래스를 만들어

야 한다. ch01-bankapp-xml 프로젝트에는 FixedDepositController, FixedDepositService,

FixedDepositDao 애플리케이션 객체에 해당하는 POJO 클래스가 있다. ch01-bankapp-xml 프

로젝트는 스프링의 DI 기능을 사용하는 간소화된 버전의 MyBank 애플리케이션이며, 이후 단계에서는

ch01-bankapp-xml 프로젝트에 포함된 파일을 살펴볼 것이므로 이 프로젝트를 IDE로 가져와야 한

다.

1-3절에서 의존성은 생성자 인자나 세터 메서드 인자를 통해 애플리케이션 객체로 전달된다고 설명했

다. 다음 예제에서는 FixedDepositController의 의존성인 FixedDepositService의 인스턴스가 세터

메서드 인자를 통해 FixedDepositController 객체로 전달되고 있다.

예제 1-12: FixedDepositController 클래스

프로젝트: ch01-bankapp-xml,

소스 위치: src/main/java/sample/spring/chapter01/bankapp

package sample.spring.chapter01.bankapp;

.....

public class FixedDepositController {

.....

private FixedDepositService fixedDepositService;

01. 스프링 프레임워크 소개 35

.....

public void setFixedDepositService(FixedDepositService fixedDepositService) {

logger.info("Setting fixedDepositService property");

this.fixedDepositService = fixedDepositService;

}

.....

public void submit() {

fixedDepositService.createFixedDeposit(new FixedDepositDetails( 1, 10000,

365, "[email protected]"));

}

.....

}

이 예제에서 FixedDepositService 의존성은 setFixedDepositService 메서드를 통해 Fixed

DepositController로 전달된다. 스프링이 setFixedDepositService 세터 메서드를 호출하는 과정은

조금 뒤에 확인한다.

FixedDepositController, FixedDepositService, FixedDepositDao 클래스를 살펴보면 이러한 클래스가 스프링 관련 인

터페이스를 구현하거나 스프링 관련 클래스를 확장하지 않는다는 것을 알 수 있다.

다음으로 구성 메타데이터에서 애플리케이션 객체와 그 의존성을 지정하는 방법을 알아보자.

구성 메타데이터 작성

앞서 1-3절에서 구성 메타데이터는 애플리케이션 객체와 그 의존성을 지정하기 위한 것이며, 스프링 컨

테이너는 구성 메타데이터를 읽고 애플리케이션 객체를 인스턴스화하며 그 의존성을 주입다고 설명했

다. 이 절에서는 먼저 구성 메타데이터에 포함된 다른 정보에 대해 알아본 후, XML 형식의 구성 메타데

이터를 작성하는 방법을 자세히 알아본다.

구성 메타데이터는 애플리케이션에 필요한 엔터프라이즈 서비스(예: 트랜잭션 관리, 보안, 원

격 접근)에 대한 정보를 지정한다. 예를 들어, 스프링이 트랜잭션을 관리하게 하려면 구성 메

타데이터에서 스프링의 PlatformTransactionManager 인터페이스의 구현을 구성해야 한다.

PlatformTransactionManager 구현은 트랜잭션을 관리한다(스프링의 트랜잭션 관리 기능은 7장을

참조한다).

36 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

애플리케이션이 메시징 미들웨어(예: ActiveMQ ), 데이터베이스(예: MySQL ), 이메일 서버 등과 상

호작용하는 경우 구성 메타데이터에서 이러한 외부 시스템과의 상호작용을 간소화하는 스프링 관련 객

체를 정의해야 한다. 예를 들어, 애플리케이션이 ActiveMQ와 JMS 메시지를 주고받는 경우 ActiveMQ

와의 상호작용을 간소화하려면 구성 메타데이터에서 스프링의 JmsTemplate 클래스를 구성해야 한다.

예제 1-10에서 JmsTemplate을 사용해 JMS 공급자로 메시지를 전송하면 저수준 JMS API를 직접 다

룰 필요가 없다는 것을 확인했다(스프링의 JMS 공급자 관련 지원은 8장을 참조한다).

구성 메타데이터를 스프링 컨테이너로 제공하려면 POJO 클래스에서 어노테이션을 사용하거나 XML

파일을 사용할 수 있다. 스프링 3.0부터는 스프링의 @Configuration 어노테이션을 지정한 자바 클

래스를 통해 구성 메타데이터를 스프링 컨테이너로 제공할 수 있게 됐다. 이 절에서는 XML 형식으

로 구성 메타데이터를 지정하는 방법을 알아보겠다. POJO 클래스에서 어노테이션을 사용하는 방법과

@Configuration 어노테이션을 지정한 자바 클래스를 통해 구성 메타데이터를 제공하는 방법은 6장에

서 알아본다.

XML 형식의 구성 메타데이터를 애플리케이션에 제공하려면 애플리케이션 객체와 그 의존성에 대

한 정보를 포함하는 애플리케이션 컨텍스트 XML 파일을 만들어야 한다. 예제 1-13은 애플리케

이션 컨텍스트 XML 파일의 예다. 이 예제는 FixedDepositController, FixedDepositService,

FixedDepositDao 객체로 구성된 MyBank 애플리케이션의 애플리케이션 컨텍스트 XML 파일이다

(이러한 객체가 상호작용하는 방법은 그림 1-4를 참조한다).

예제 1-13: applicationContext.xml - MyBank의 애플리케이션 컨텍스트 XML 파일

프로젝트: ch01-bankapp-xml,

소스 위치: src/main/resources/META-INF/spring

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<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.0.xsd">

<bean id="controller"

class="sample.spring.chapter01.bankapp.FixedDepositController">

<property name="fixedDepositService" ref="service" />

</bean>

01. 스프링 프레임워크 소개 37

<bean id="service" class="sample.spring.chapter01.bankapp.FixedDepositService">

<property name="fixedDepositDao" ref="dao" />

</bean>

<bean id="dao" class="sample.spring.chapter01.bankapp.FixedDepositDao"/>

</beans>

이 애플리케이션 컨텍스트 XML 파일에서 주의해서 확인할 사항은 다음과 같다.

■ <beans> 요소는 애플리케이션 컨텍스트 XML 파일의 루트 요소이며, spring-beans-4.0.xsd 스키마(스프링 beans

스키마라고도 한다)에 정의돼 있다. spring-beans-4.0.xsd 스키마는 스프링 프레임워크 배포판과 함께 제공되는

spring-beans-4.0.0.RELEASE.jar JAR 파일에 포함돼 있다.

■ 각 <bean> 요소는 스프링 컨테이너가 관리하는 애플리케이션 객체 하나를 구성한다. 스프링 프레임워크의 용어로 설

명하면 <bean> 요소는 빈 정의에 해당한다. 스프링 컨테이너가 빈 정의에 따라 생성하는 객체를 빈이라고 한다. id 특

성에는 빈의 고유한 이름을 지정하며, class 특성에는 빈의 정규화된 클래스 이름을 지정한다. <bean> 요소의 name

특성을 사용해 빈 별칭을 지정할 수도 있다. MyBank 애플리케이션의 애플리케이션 객체는 FixedDepositController,

FixedDepositService, FixedDepositDao이므로 애플리케이션 객체당 하나씩 3개의 <bean> 요소가 있다. <bean> 요

소로 구성한 애플리케이션 객체는 스프링 컨테이너가 관리하며 이 애플리케이션 객체를 생성하고 그 의존성을 주입하

는 역할도 스프링 컨테이너가 한다. <bean> 요소로 정의한 애플리케이션 객체의 인스턴스는 개발자가 직접 생성하지

않고 스프링 컨테이너로부터 얻는다. 이 절의 후반부에서는 스프링 컨테이너가 관리하는 애플리케이션 객체를 얻는 방

법을 살펴보겠다.

■ MyBank 애플리케이션의 FixedDepositDetails 도메인 객체에 해당하는 <bean> 요소는 정의하지 않았다. 그 이유

는 도메인 객체는 일반적으로 스프링 컨테이너가 관리하지 않기 때문이다. 도메인 객체는 애플리케이션에서 사용하는

ORM 프레임워크(예: 하이버네이트)에서 생성하거나 개발자가 new 연산자를 이용해 프로그래밍 방식으로 생성한다.

■ <property> 요소에는 <bean> 요소로 구성하는 빈의 의존성(또는 구성 속성)을 지정한다. <property> 요소는 스프링 컨

테이너가 빈의 의존성(또는 구성 속성)을 설정하기 위해 호출하는 빈 클래스의 자바빈 스타일 세터 메서드와 연결된다.

다음으로 세터 메서드가 의존성을 주입하는 방법을 살펴보자.

세터 메서드를 통한 의존성 주입

빈 클래스에 정의된 세터 메서드를 통해 의존성이 주입되는 방법을 설명하기 위해 MyBank 애플리케이

션의 FixedDepositController 클래스를 다시 살펴보자.

38 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

예제 1-14: FixedDepositController 클래스

프로젝트: ch01-bankapp-xml

소스 위치: src/main/java/sample/spring/chapter01/bankapp

package sample.spring.chapter01.bankapp;

import org.apache.log4j.Logger;

public class FixedDepositController {

private static Logger logger = Logger.getLogger(FixedDepositController.class);

private FixedDepositService fixedDepositService;

public FixedDepositController() {

logger.info("initializing");

}

public void setFixedDepositService(FixedDepositService fixedDepositService) {

logger.info("Setting fixedDepositService property");

this.fixedDepositService = fixedDepositService;

}

.....

}

이 예제에서 FixedDepositController 클래스는 FixedDepositService 형식의 fixedDeposit

Service 인스턴스 변수를 선언했으며, fixedDepositService 변수는 이 변수의 자바빈 스타일 세터 메

서드인 setFixedDepositService 메서드에서 설정된다. 이것이 세터 메서드로 의존성을 해결하는 세터

기반 DI의 한 예다.

다음 그림은 applicationContext.xml 파일(예제 1-13 참조)에 있는 FixedDepositController 클래

스의 빈 정의를 설명한다.

01. 스프링 프레임워크 소개 39

<property> 요소에는 의존성을

지정한다.

name 특성은 빈의 자바빈 스타일 세터 메서드를 가리킨다.

세터 메서드는 ref 특성으로 지정된 빈과 동일한 형식의 인자를 받는다.

ref 특성에는 구성 메타데이터의 다른 빈을 지정한다. 지정된 빈은

name 특성과 연결된 자바빈 스타일의 세터 메서드로 전달된다.

<bean id="controller" class="sample.spring.chapter01.bankapp.FixedDepositController">

<property name="fixedDepositService" ref="service" />

</bean>

그림 1-5 <property> 요소로 의존성을 정의하는 예

이 빈 정의에서 FixedDepositController 빈은 <property> 요소로 FixedDepositService 빈에 대한

의존성을 정의했다. <property> 요소의 name 특성에는 스프링 컨테이너가 빈을 생성할 때 호출할 빈

클래스의 자바빈 스타일 세터 메서드를 지정한다. <property> 요소의 ref 특성에는 인스턴스를 생성하

고 자바빈 스타일 세터 메서드로 전달해야 하는 스프링 빈을 지정한다. ref 특성 값은 구성 메타데이터에

서 <bean> 요소의 id 특성 값(또는 name 특성으로 지정한 이름 중 하나)과 일치해야 한다.

그림 1-5에서 <property> 요소의 name 특성 값은 fixedDepositService다. 즉, 이 <property>

요소는 FixedDepositController 클래스(예제 1-14 )의 setFixedDepositService 세터 메서드

와 연결된다. <property> 요소의 ref 특성 값은 service이므로 이 요소는 id 특성 값이 service인

<bean> 요소를 가리킨다. id 특성 값이 service인 <bean> 요소는 FixedDepositService 빈(예제

1-13 )이다. 스프링 컨테이너는 FixedDepositService 클래스(의존성)의 인스턴스를 생성한 다음

FixedDepositController (의존 객체)의 setFixedDepositService 메서드(fixedDepositService 변

수의 자바빈 스타일 세터 메서드)로 FixedDepositService 인스턴스를 전달하고 호출한다.

다음 그림은 FixedDepositController 애플리케이션 객체에서 <property> 요소의 name 및 ref 특성

의 목적을 간단하게 보여준다.

40 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

<bean id="controller"

class="sample.spring.chapter01.bankapp.FixedDepositController">

<property name="fixedDepositService" ref="service" />

</bean>

<bean id="service"

class="sample.spring.chapter01.bankapp.FixedDepositService"

<property name="fixedDepositDao" ref="dao" />

</bean>

public class FixedDepositController {

...

private FixedDepositService fixedDepositService;

...

public void setFixedDepositService(

FixedDepositService fixedDepositService) {

logger.info("Setting fixedDepositService property");

this.fixedDepositService = fixedDepositService;

}

...

}

그림 1-6 <property> 요소의 name 특성에는 빈 의존성을 충족하는 자바빈 스타일의 세터 메서드를 지정하며, ref 특성은 다른

빈을 가리킨다.

이 그림에서 name 특성 값인 fixedDepositService는 FixedDepositController 클래스의 setFixed

DepositService 메서드에 해당하며, ref 특성 값인 service는 id가 service인 빈을 가리킨다.

빈 정의를 이름(id 특성 값)이나 형식(class 특성 값) 또는 빈 클래스가 구현하는 인터페이스 이름으로 부르

는 경우를 자주 볼 수 있다. 예를 들어, ‘FixedDepositController 빈’을 ‘controller 빈’이라고 할 수 있으며,

FixedDepositController 클래스가 FixedDepositControllerIntf 인터페이스를 구현하는 경우 ‘FixedDepositController 빈’

을 ‘FixedDepositControllerIntf 빈’이라고 할 수 있다.

다음 다이어그램에는 스프링 컨테이너가 MyBank 애플리케이션의 applicationContext.xml 파일(예

제 1-13 )에 지정된 구성 메타데이터를 바탕으로 빈을 생성하고 그 의존성을 주입하는 방법이 요약돼 있

다.

01. 스프링 프레임워크 소개 41

스프링 컨테이너 구성 메타데이터

FixedDepositController

FixedDepositService

FixedDepositDao

읽기

유효성 검사

생성

생성

생성

setFixedDepositDao(FixedDepositDao)

setFixedDepositService(FixedDepositService)

그림 1-7 스프링 IoC 컨테이너가 빈을 생성하고 그 의존성을 주입하는 순서

이 그림에는 스프링 IoC 컨테이너가 FixedDepositController, FixedDepositService,

FixedDepositDao 빈을 생성하고 그 의존성을 주입하는 단계가 나온다. 스프링 컨테이너는 맨

먼저 applicationContext.xml 파일에 제공된 구성 메타데이터를 읽고 유효성을 검사한 다음

applicationContext.xml 파일에 정의된 순서대로 빈을 생성한다. 또한 스프링 컨테이너는 세터 메

서드를 호출하기 전에 빈의 의존성을 완전하게 구성한다. 예를 들어, FixedDepositController 빈

은 FixedDepositService 빈에 의존하므로 스프링 컨테이너는 FixedDepositController 빈의

setFixedDepositService 메서드를 호출하기 전에 FixedDepositService 빈을 구성한다.

지금까지 살펴본 빈 정의에서는 빈 클래스의 인자가 없는 생성자를 호출해 빈 인스턴스를 생성한 후 세

터 기반 DI를 사용해 의존성을 주입하도록 스프링 컨테이너에 지시했다. 2장에서는 클래스에 정의된 팩

터리 메서드를 통해 빈 인스턴스를 생성하도록 스프링 컨테이너에 지시하는 빈 정의에 대해 알아보겠다.

그리고 생성자 인자를 통해 의존성을 주입하는 방법(생성자 기반 DI라고 한다), 빈 인스턴스를 생성하

는 팩터리 메서드의 인자를 통해 의존성을 주입하는 방법, 그리고 팩터리 메서드가 반환한 빈 인스턴스

에 세터 기반 DI를 사용하는 방법도 알아본다.

이제 스프링 컨테이너의 인스턴스를 만들고 구성 메타데이터를 전달하는 방법을 알아보자.

42 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

스프링 컨테이너의 인스턴스 생성

스프링의 ApplicationContext 객체는 스프링 컨테이너의 인스턴스다. 스프링은 ApplicationContext

인터페이스의 몇 가지 기본 구현(예: ClassPathXmlApplicationContext, FileSystemXmlApplicat

ionContext, XmlWebApplicationContext, XmlPortletApplicationContext 등)을 제공한다. 어

떤 ApplicationContext 구현을 선택할지는 구성 메타데이터를 정의한 방법(XML, 어노테이션 또는

자바 코드)과 애플리케이션의 종류(독립형, 웹 또는 포틀릿 애플리케이션)에 따라 달라진다. 예를 들어,

ClassPathXmlApplicationContext 및 FileSystemXmlApplicationContext 클래스는 구성 메타데

이터가 XML 형식으로 제공된 독립형 애플리케이션에 적합하고, XmlWebApplicationContext는 구

성 메타데이터가 XML 형식으로 제공된 웹 애플리케이션에 적합하며, AnnotationConfigWebApplic

ationContext는 구성 메타데이터가 자바 코드로 제공되는 웹 애플리케이션에 적합하다.

MyBank 애플리케이션은 독립형 애플리케이션이므로 ClassPathXmlApplicationContext 또는

FileSystemXmlApplicationContext 클래스를 사용해 스프링 컨테이너의 인스턴스를 생성할 수 있

다. ClassPathXmlApplicationContext 클래스는 지정된 classpath 위치에서 애플리케이션 컨텍스트

XML 파일을 읽고, FileSystemXmlApplicationContext 클래스는 파일 시스템 상의 지정된 위치에서

애플리케이션 컨텍스트 XML 파일을 읽는다.

다음 예제의 BankApp 클래스는 ClassPathXmlApplicationContext 클래스를 사용해 스프링 컨테이

너의 인스턴스를 생성했다.

예제 1-15: BankApp 클래스

프로젝트: ch01-bankapp-xml,

소스 위치: src/main/java/sample/spring/chapter01/bankapp

package sample.spring.chapter01.bankapp;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BankApp {

.....

public static void main(String args[]) {

ApplicationContext context = new ClassPathXmlApplicationContext(

"classpath:META-INF/spring/applicationContext.xml");

.....

}

}

01. 스프링 프레임워크 소개 43

이 예제에 나오는 BankApp의 main 메서드는 스프링 컨테이너를 기동하는 역할을 한다. 애플리케이

션 컨텍스트 XML 파일의 classpath 위치는 ClassPathXmlApplicationContext 클래스의 생성자로

전달됐다. ClassPathXmlApplicationContext 인스턴스를 생성하면 애플리케이션 컨텍스트 XML 파

일에 정의된 빈이 싱글톤 범위(singleton-scoped ) 및 사전 인스턴스화(pre-instantiated ) 설정으

로 생성된다. 빈 범위와 스프링 컨테이너의 사전 인스턴스화 및 지연 인스턴스화의 의미는 2장에서 설

명할 것이므로, 일단은 MyBank 애플리케이션의 applicationContext.xml 파일에 정의된 빈이 싱글

톤 범위이며, 사전 인스턴스화된다고만 알아두자. 즉, applicationContext.xml 파일에 정의된 빈은

ClassPathXmlApplicationContext의 인스턴스가 생성될 때 함께 생성된다.

지금까지 스프링 컨테이너의 인스턴스를 생성하는 방법을 알아봤다. 다음으로 스프링 컨테이너에서 빈

인스턴스를 얻는 방법을 알아보자.

스프링 컨테이너의 빈에 접근하기

스프링 컨테이너는 <bean> 요소로 정의된 애플리케이션 객체를 생성하고 관리한다. 이러한 애플리케이

션 객체의 인스턴스에 접근하려면 ApplicationContext 인터페이스의 getBean 메서드 중 하나를 호출

하면 된다.

다음 예제에 나오는 BankApp 클래스의 main 메서드는 스프링 컨테이너에서 FixedDeposit

Controller 빈의 인스턴스를 얻고 이 인스턴스의 메서드를 호출한다.

예제 1-16: BankApp 클래스

프로젝트: ch01-bankapp-xml,

소스 위치: src/main/java/sample/spring/chapter01/bankapp

package sample.spring.chapter01.bankapp;

import org.apache.log4j.Logger;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class BankApp {

private static Logger logger = Logger.getLogger(BankApp.class);

public static void main(String args[]) {

ApplicationContext context = new ClassPathXmlApplicationContext(

44 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

"classpath:META-INF/spring/applicationContext.xml");

FixedDepositController fixedDepositController =

FixedDepositController) context.getBean("controller");

logger.info("Submission status of fixed deposit : " + fixedDepositController.submit());

logger.info("Returned fixed deposit info : " + fixedDepositController.get());

}

}

이 예제에서는 ApplicationContext의 getBean 메서드를 호출해 스프링 컨테이너에서 Fixed

DepositController 빈의 인스턴스를 얻고 이 인스턴스의 submit 및 get 메서드를 호출했다. getBean

메서드에는 스프링 컨테이너에서 인스턴스를 얻으려는 빈의 이름을 인자로 지정했다. getBean 메서드

에 지정하는 빈의 이름은 얻으려는 빈의 id 또는 name 특성 값이어야 한다. 스프링 컨테이너에 등록된

빈 중 지정된 이름의 빈이 없는 경우 getBean 메서드에서 예외가 발생한다.

예제 1-16을 보면 FixedDepositController 인스턴스를 구성하기 위해 프로그래밍 방식으로 Fixed

DepositService의 인스턴스를 만들고 FixedDepositController 인스턴스에서 이를 설정하는 코드는

물론이고 FixedDepositDao의 인스턴스를 만들고 FixedDepositService 인스턴스에서 이를 설정하

는 코드도 없다는 것을 알 수 있다. 그 이유는 의존성을 생성하고 이를 의존 객체로 주입하는 작업을 스

프링 컨테이너가 담당하기 때문이다.

ch01-bankapp-xml 프로젝트에서 BankApp 클래스의 main 메서드를 실행하면 콘솔에 다음과 같

은 결과가 출력된다.

INFO sample.spring.chapter01.bankapp.FixedDepositController - initializing

INFO sample.spring.chapter01.bankapp.FixedDepositService - initializing

INFO sample.spring.chapter01.bankapp.FixedDepositDao - initializing

INFO sample.spring.chapter01.bankapp.FixedDepositService - Setting fixedDepositDao property

INFO sample.spring.chapter01.bankapp.FixedDepositController - Setting fixedDepositService

property

INFO sample.spring.chapter01.bankapp.BankApp - Submission status of fixed deposit : true

INFO sample.spring.chapter01.bankapp.BankApp - Returned fixed deposit info : id :1, deposit

amount : 10000.0, tenure : 365, email : [email protected]

출력 결과를 보면 스프링 컨테이너가 MyBank 애플리케이션의 applicationContext.xml 파일

에 정의된 각 빈 인스턴스를 생성했음을 알 수 있다. 또한 스프링 컨테이너가 세터 기반 DI를 사용

01. 스프링 프레임워크 소개 45

해 FixedDepositService의 인스턴스를 FixedDepositController 인스턴스로 주입하고 Fixed

DepositDao의 인스턴스를 FixedDepositService 인스턴스로 주입했다는 것도 확인할 수 있다.

이어서 스프링 프레임워크를 기반으로 개발된 몇 가지 프레임워크에 대해 알아보자.

1-6 스프링 기반의 다른 프레임워크 프로젝트

스프링소스(SpringSource )에서는 스프링 프레임워크를 기반으로 다양한 프레임워크를 개발했는데,

그중 널리 알려진 몇 가지를 알아보자. 전체 프레임워크 목록과 개별 프레임워크에 대한 자세한 내용은

스프링소스 웹 사이트(www.springsource.org )를 참고한다.

다음 표는 스프링소스에서 스프링 프레임워크를 기반으로 개발한 프레임워크를 정리한 것이다.

프레임워크 설명

스프링 시큐리티(Spring Security) 엔터프라이즈 애플리케이션을 위한 인증 및 권한 부여 프레임워크다. 애플리케이션에 인증

및 권한 부여 기능을 통합하려면 애플리케이션 컨텍스트 XML 파일에서 몇 가지 빈을 구성

해야 한다.

스프링 데이터(Spring Data) 다양한 종류의 데이터베이스와 상호작용하기 위한 일관된 프로그래밍 모델을 제공한다. 이

프레임워크는 MongoDB 또는 Neo4j와 같은 관계형이 아닌 데이터베이스와 상호작용하는

데는 물론 JPA를 통해 관계형 데이터베이스에 접근하는 데도 사용할 수 있다.

스프링 배치(Spring Batch) 대량의 처리가 필요한 애플리케이션이라면 이 프레임워크를 선택하면 된다.

스프링 인티그레이션(Spring

Integration)

애플리케이션에 엔터프라이즈 애플리케이션 통합(EAI; Enterprise Application Integration)

기능을 제공한다.

스프링 소셜(Spring Social) 애플리케이션에 페이스북이나 트위터 같은 소셜 미디어 웹 사이트와의 상호작용 기능이 필

요한 경우 매우 유용한 프레임워크다.

스프링 BlazeDS 통합(Spring

BlazeDS Integration)

어도비 플렉스 기반 애플리케이션을 개발하는 경우 이 프레임워크를 사용해 플렉스 프런트

엔드와 스프링 기반 비즈니스 티어를 연결할 수 있다.

이 표에 소개된 프레임워크는 스프링 프레임워크에 기반을 두고 있으므로 이러한 프레임워크를 사용하

려면 먼저 현재 사용 중인 스프링 프레임워크 버전과 호환되는지 확인해야 한다.

1-7 요약

1장에서는 스프링 프레임워크의 장점을 알아봤다. 구성 메타데이터를 XML 형식으로 지정하는 방법을

보여주는 간단한 스프링 애플리케이션을 살펴봤으며, 스프링 컨테이너 인스턴스를 생성하고 빈을 가져

오는 방법을 알아봤다. 다음 장에서는 스프링 프레임워크의 몇 가지 기본적인 개념을 설명한다.

46 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

2-1 소개

1장에서는 스프링 컨테이너가 빈 클래스의 인자가 없는 생성자를 호출해 빈 인스턴스를 생성하고 세터

기반 DI로 빈 의존성을 설정하는 것을 확인했다. 2장에서는 다음 단계에 해당하는 다음과 같은 내용을

알아본다.

■ ‘인터페이스 기반 프로그래밍’ 설계 원칙을 위한 스프링의 지원

■ 스프링 빈을 인스턴스화하는 다양한 방법

■ 빈 의존성을 생성자 인자로 전달하는 생성자 기반 DI

■ 간단한 문자열 값을 빈으로 전달하는 생성자 기반 및 세터 기반 DI

■ 빈의 범위

2장에서는 먼저 스프링이 애플리케이션을 쉽게 테스트할 수 있게 ‘인터페이스 기반 프로그래밍’ 설계 원

칙을 지원하는 방법을 알아보는 것으로 시작하자.

2-2 인터페이스 기반 프로그래밍 설계 원칙

1장의 1-5절을 보면 의존 POJO 클래스에 의존성의 구상 클래스(concrete class ) 참조가 포함돼 있

었다. 예를 들어, FixedDepositController 클래스에 FixedDepositService 클래스 참조가 있었고

스프링 프레임워크 기초

02

02. 스프링 프레임워크 기초 47

FixedDepositService 클래스에 FixedDepositDao 클래스 참조가 있었다. 의존 클래스에 의존성의

구상 클래스에 대한 직접 참조가 있으면 클래스 사이에 긴밀한 결합이 발생해 의존성을 다른 구현으로

바꾸려는 경우 의존 클래스까지 변경해야 하는 부작용이 있다.

의존 클래스가 의존성의 구상 클래스를 직접 참조하는 경우를 먼저 확인해보자.

시나리오: 의존 클래스가 의존성의 구상 클래스를 참조하는 경우

FixedDepositDao 클래스가 데이터베이스와 상호작용하기 위해 일반 JDBC를 사용한다고 가정해

보자. 그런데 나중에 데이터베이스 상호작용을 간소화하기 위해 하이버네이트 ORM을 사용해 데이터

베이스 상호작용을 수행하는 FixedDepositHibernateDao라는 DAO 구현을 만들었다면 이를 어

떻게 사용할 수 있을까? 일반 JDBC 구현을 하이버네이트 ORM 구현으로 바꾸려면 다음 예제처럼

FixedDepositDao 대신 FixedDepositHibernateDao를 사용하도록 FixedDepositService 클래스

를 수정해야 한다.

예제 2-1: FixedDepositService 클래스

public class FixedDepositService {

private FixedDepositHibernateDao fixedDepositDao;

public void setFixedDepositDao(FixedDepositHibernateDao fixedDepositDao) {

this.fixedDepositDao = fixedDepositDao;

}

public FixedDepositDetails getFixedDepositDetails(long id) {

return fixedDepositDao.getFixedDepositDetails(id);

}

public boolean createFixedDeposit(FixedDepositDetails fixedDepositDetails) {

return fixedDepositDao.createFixedDeposit(fixedDepositDetails);

}

}

이 예제를 보면 데이터베이스 상호작용에 하이버네이트 ORM을 사용하기 위해 FixedDepositDao 클

래스 참조를 FixedDepositHibernateDao로 바꾼 것을 알 수 있다. 즉, 의존 클래스가 의존성의 구체

적인 구현 클래스를 참조하는 경우 의존성을 다른 구현으로 대체하려면 의존 클래스까지 변경해야 한다.

다음으로 의존 클래스가 의존성이 구현하는 인터페이스 참조를 사용하는 경우를 확인해보자.

시나리오: 의존 클래스가 의존성이 구현하는 인터페이스 참조를 사용하는 경우

알다시피, 자바 인터페이스는 구현 클래스가 준수하는 계약을 정의한다. 즉, 클래스가 의존성이 구현

하는 인터페이스에 의존하는 경우 의존성의 구현을 바꾸더라도 클래스는 변경할 필요가 없다. 클래스

가 의존성이 구현하는 인터페이스에 의존하는 애플리케이션 설계 방식을 ‘인터페이스 기반 프로그래밍

(programming to interface )’이라고 한다. 그리고 의존성 클래스가 구현한 인터페이스를 의존성 인터

페이스라고 한다.

인터페이스 기반 프로그래밍은 클래스 기반 프로그래밍보다 좋은 설계 방법이다. 즉, 다음 다이어그램에

서 ABean 클래스가 BBean 인터페이스에 의존하는 경우 좋은 설계지만, ABean 클래스가 BBean 인

터페이스를 구현하는 BBeanImpl 클래스에 의존하는 경우 나쁜 설계에 해당한다.

그림 2-1 인터페이스 기반 프로그래밍은 클래스 기반 프로그래밍보다 좋은 설계 방법이다.

다음 클래스 다이어그램은 FixedDepositService 클래스가 인터페이스 기반 프로그래밍 설계 방법을

사용해 데이터베이스 상호작용 전략을 손쉽게 전환하는 예를 보여준다.

그림 2-2 FixedDepositService는 FixedDepositJdbcDao 및 FixedDepositHibernateDao 클래스가 구현하는 FixedDepositDao

인터페이스에 의존한다.

02. 스프링 프레임워크 기초 49

이 그림에서 FixedDepositService 클래스는 FixedDepositJdbcDao 또는 FixedDeposit

HibernateDao 클래스에 직접 의존하지 않고 이러한 클래스가 구현하는 FixedDepositDao 인터

페이스(의존성 인터페이스)에 의존한다. 이제 일반 JDBC나 하이버네이트 ORM 프레임워크 중 어

떤 것을 원하느냐에 따라 FixedDepositJdbcDao 또는 FixedDepositHibernateDao의 인스턴스를

FixedDepositService 인스턴스에 제공하면 된다.

FixedDepositService는 FixedDepositDao 인터페이스에 의존하므로 향후 다른 데이터베이스 상

호작용 전략을 지원하는 것도 가능하다. 예를 들어, iBATIS (현재는 MyBatis ) 영속성 프레임워크

를 데이터베이스 상호작용에 사용하기로 결정한 경우 FixedDepositService 클래스를 변경할 필요

없이 FixedDepositDao 인터페이스를 구현하는 FixedDepositIbatisDao 클래스를 새로 만들고

FixedDepositIbatisDao의 인스턴스를 FixedDepositService 인스턴스로 제공하면 된다.

지금까지 ‘인터페이스 기반 프로그래밍’ 설계 방법을 통해 의존 클래스와 그 의존성 간의 결합을 느슨하

게 만들 수 있음을 확인했다. 다음으로 이 설계 방법을 사용했을 때 의존 클래스를 테스트하기가 얼마나

편해지는지 알아보자.

의존 클래스를 편리하게 테스트하기

그림 2-2에서 FixedDepositService 클래스는 FixedDepositDao 인터페이스 참조를 포함하며,

FixedDepositJdbcDao 및 FixedDepositHibernateDao는 FixedDepositDao 인터페이스의 구체

적인 구현 클래스다. 이 경우 FixedDepositService 클래스를 단위 테스트하려면 FixedDepositDao

인터페이스를 데이터베이스가 필요 없는 모의 구현(mock implementation )으로 바꾸면 된다.

FixedDepositService 클래스가 FixedDepositJdbcDao 또는 FixedDepositHibernateDao 클래

스에 대한 직접 참조를 사용하는 경우 FixedDepositService 클래스를 테스트하려면 데이터베이스를

설정해야 하기 때문에 번거롭다. 즉, 의존성 인터페이스의 모의 구현을 사용하면 의존 클래스를 단위 테

스트할 때 인프라를 구성하는 복잡한 작업이 필요하지 않다.

이제 스프링이 인터페이스 기반 프로그래밍을 어떻게 지원하고 있는지 확인해보자.

인터페이스 기반 프로그래밍 설계 방법을 위한 스프링 지원

스프링 애플리케이션에서 인터페이스 기반 프로그래밍 설계 방법을 따르려면 다음과 같은 사항을 지켜

야 한다.

50 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

■ 구성 메타데이터의 <bean> 요소에는 의존성의 구상 클래스를 지정한다.

■ 의존 빈 클래스는 의존성의 구상 클래스가 아닌 의존성 인터페이스를 참조한다.

다음으로 인터페이스 기반 프로그래밍 설계 방법에 따라 수정한 MyBank 애플리케이션이다.

예제 프로젝트: chapter 2/ch02-bankapp-interfaces (이 프로젝트는 인터페이스 기반 프로그래밍 설계 방법을 적용한

스프링 애플리케이션의 예를 보여준다. 이 애플리케이션을 실행하려면 이 프로젝트에서 BankApp 클래스의 main 메서

드를 실행한다.)

인터페이스 기반 프로그래밍 설계 방법을 사용하는 MyBank 애플리케이션

다음 클래스 다이어그램은 인터페이스 기반 프로그래밍 설계 방법을 사용하도록 수정된 MyBank 애플

리케이션을 나타낸 것이다.

그림 2-3 인터페이스 기반 프로그래밍 설계 방법을 사용하는 MyBank 애플리케이션

이 그림에서 의존 클래스는 의존성의 구체적인 구현 클래스가 아닌 의존성이 구현하는 인터페이스에 의

존한다. 예를 들어, FixedDepositControllerImpl 클래스는 FixedDepositService 인터페이스에 의

존하며 FixedDepositServiceImpl 클래스는 FixedDepositDao 인터페이스에 의존한다.

다음 예제에는 그림 2-3의 설계를 기반으로 작성한 FixedDepositServiceImpl 클래스다.

02. 스프링 프레임워크 기초 51

예제 2-2: FixedDepositService 클래스

프로젝트: ch02-bankapp-interfaces,

소스 위치: src/main/java/sample/spring/chapter02/bankapp

package sample.spring.chapter02.bankapp;

public class FixedDepositServiceImpl implements FixedDepositService {

private FixedDepositDao fixedDepositDao;

.....

public void setFixedDepositDao(FixedDepositDao fixedDepositDao) {

this.fixedDepositDao = fixedDepositDao;

}

public FixedDepositDetails getFixedDepositDetails(long id) {

return fixedDepositDao.getFixedDepositDetails(id);

}

public boolean createFixedDeposit(FixedDepositDetails fdd) {

return fixedDepositDao.createFixedDeposit(fdd);

}

}

이 예제에서 FixedDepositServiceImpl 클래스에는 FixedDepositDao 인터페이스에 대한 참조가

포함돼 있으며, FixedDepositServiceImpl 인스턴스로 주입할 FixedDepositDao 구현은 애플리케

이션 컨텍스트 XML 파일에서 지정한다. 그림 2-3에 나오는 것처럼 주입할 FixedDepositDao 인터페

이스의 구현체는 FixedDepositIbatisDao, FixedDepositJdbcDao, FixedDepositHibernateDao

중에서 선택할 수 있다.

다음 예제는 그림 2-3의 설계에 사용되는 applicationContext.xml 파일이다.

예제 2-3: applicationContext.xml - MyBank의 애플리케이션 컨텍스트 XML 파일

프로젝트: ch02-bankapp-interfaces,

소스 위치: src/main/resources/META-INF/spring

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<beans .....>

<bean id="controller"

52 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

class="sample.spring.chapter02.bankapp.controller.FixedDepositControllerImpl">

<property name="fixedDepositService" ref="service" />

</bean>

<bean id="service" class="sample.spring.chapter02.bankapp.service.FixedDepositServiceImpl">

<property name="fixedDepositDao" ref="dao" />

</bean>

<bean id="dao" class="sample.spring.chapter02.bankapp.dao.FixedDepositHibernateDao"/>

</beans>

이 applicationContext.xml 파일에서는 FixedDepositHibernateDao의 인스턴스(Fixed

DepositDao 인터페이스의 구현)를 FixedDepositServiceImpl로 주입하도록 설정돼 있다. 나중에

영속성 기능에 하이버네이트 대신 iBATIS를 사용하게끔 변경하려면 applicationContext.xml 파일에

서 dao 빈 정의의 class 특성에 FixedDepositIbatisDao 클래스의 정규화된 이름을 지정하면 된다.

그럼 이번에는 스프링 컨테이너가 빈을 인스턴스화하는 다른 방법을 살펴보자.

2-3 스프링 빈을 인스턴스화하는 다른 방법

지금까지 살펴본 빈 정의에서는 빈 클래스의 인자가 없는 생성자를 호출해 빈 인스턴스를 생성하도록 스

프링 컨테이너에 지시하는 방법을 사용했다. 다음 빈 정의를 살펴보자.

<bean id="myBean" class="mypackage.MyBean"/>

이 빈 정의에서 MyBean 클래스는 인자가 없는 생성자를 정의하는 POJO 클래스다. MyBean 클래스

는 스프링 관련 인터페이스를 구현하거나 스프링 관련 클래스를 확장하지 않는다. 즉, 스프링 컨테이너

는 인자가 없는 생성자를 제공하는 모든 클래스의 인스턴스를 생성하고 관리할 수 있다.

사실 스프링 컨테이너는 클래스가 인자가 없는 생성자를 제공하는지 여부와 관계없이 모든 클래스의 인스턴스를 생성

하고 관리할 수 있다. 2-4절에서는 생성자가 인자를 하나 이상 받는 빈 클래스의 빈 정의를 살펴보겠다.

02. 스프링 프레임워크 기초 53

기존 프로젝트에서 팩터리 클래스를 사용해 객체 인스턴스를 생성하는 경우에도 이러한 팩터리에서 생

성한 객체를 스프링 컨테이너에서 관리할 수 있다. 이어서 스프링 컨테이너가 클래스의 정적 또는 인스

턴스 팩터리 메서드를 호출하고 반환된 객체 인스턴스를 관리하는 방법을 살펴보자.

정적 팩터리 메서드를 이용한 빈 인스턴스화

그림 2-3에서 FixedDepositDao 인터페이스는 FixedDepositHibernateDao, Fixed

DepositIbatisDao, FixedDepositJdbcDao 클래스에서 구현하고 있다. 다음 예제의 FixedDeposit

DaoFactory 클래스에서는 정적 메서드에 전달되는 인자를 기준으로 FixedDepositDao의 인스턴스

를 생성하고 반환하는 정적 팩터리 메서드를 정의한다.

예제 2-4: FixedDepositDaoFactory 클래스

public class FixedDepositDaoFactory {

private FixedDepositDaoFactory() { }

public static FixedDepositDao getFixedDepositDao(String daoType) {

FixedDepositDao fixedDepositDao = null;

if("jdbc".equalsIgnoreCase(daoType)) {

fixedDepositDao = new FixedDepositJdbcDao();

}

if("hibernate".equalsIgnoreCase(daoType)) {

fixedDepositDao = new FixedDepositHibernateDao();

}

.....

return fixedDepositDao;

}

}

이 예제에서 FixedDepositDaoFactory 클래스에 정의된 getFixedDepositDao 정적 메서드는

daoType 인자 값에 따라 FixedDepositJdbcDao, FixedDepositHibernateDao 또는 Fixed

DepositIbatisDao 클래스의 인스턴스를 생성하고 반환한다.

54 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

다음 FixedDepositDaoFactory 클래스의 빈 정의는 FixedDepositDaoFactory의 getFixed

DepositDao 메서드를 호출해 FixedDepositJdbcDao 클래스의 인스턴스를 얻도록 스프링 컨테이너

에 지시한다.

예제 2-5: FixedDepositDaoFactory 클래스의 빈 정의

<bean id="dao" class="sample.spring.FixedDepositDaoFactory"

factory-method="getFixedDepositDao">

<constructor-arg index="0" value="jdbc"/>

</bean>

이 빈 정의에서 class 특성에는 정적 팩터리 메서드를 정의하는 클래스의 정규화된 이름을 지정하며,

factory-method 특성에는 스프링 컨테이너가 FixedDepositDao 객체의 인스턴스를 얻기 위해 호출

하는 정적 팩터리 메서드의 이름을 지정한다. <constructor-arg> 요소는 스프링 beans 스키마에 정

의되며 생성자, 정적 및 인스턴스 팩터리 메서드로 인자를 전달하는 데 사용된다. index 특성에는 생성

자, 정적 또는 인스턴스 팩터리 메서드에서 인자의 위치를 지정한다. 이 빈 정의에서 index 특성 값 0은

<constructor-arg> 요소가 첫 번째 인자, 즉 getFixedDepositDao 팩터리 메서드의 daoType 인자

에 값을 제공한다는 의미다. value 특성에는 인자 값을 지정한다. 팩터리 메서드의 인자가 여러 개인 경

우 인자 수만큼 <constructor-arg> 요소를 정의해야 한다.

중요한 것은 dao 빈을 얻기 위해 ApplicationContext의 getBean 메서드를 호출하면(예제 2-5 )

FixedDepositDaoFactory의 getFixedDepositDao 팩터리 메서드가 호출된다는 것이다. 즉,

getBean ("dao")을 호출하면 FixedDepositDaoFactory 클래스의 인스턴스가 반환되는 것이 아니라

getFixedDepositDao 팩터리 메서드가 생성한 FixedDepositDao 인스턴스가 반환된다.

지금까지 FixedDepositDao의 인스턴스를 생성하는 팩터리 클래스의 구성을 확인했다. 다음 예제에서

는 FixedDepositDao의 인스턴스를 FixedDepositServiceImpl 클래스로 주입하는 방법을 볼 수 있

다.

예제 2-6: 정적 팩터리 메서드로 생성한 객체 인스턴스 주입

<bean id="service" class="sample.spring.chapter02.bankapp.FixedDepositServiceImpl">

<property name="fixedDepositDao" ref="dao" />

</bean>

02. 스프링 프레임워크 기초 55

<bean id="dao" class="sample.spring.chapter02.basicapp.FixedDepositDaoFactory"

factory-method="getFixedDepositDao">

<constructor-arg index="0" value="jdbc"/>

</bean>

이 예제에서 <property> 요소는 FixedDepositDaoFactory의 getFixedDepositDao 팩터리 메서

드가 반환한 FixedDepositDao의 인스턴스를 FixedDepositServiceImpl 인스턴스로 주입한다.

FixedDepositServiceImpl 클래스의 빈 정의는 예제 2-3에 나오는 빈 정의와 완전히 동일하다. 즉,

스프링 컨테이너가 빈 인스턴스를 생성한 방법(인자가 없는 생성자 또는 정적 팩터리 메서드)에 관계없

이 빈 의존성을 지정하는 방법은 동일하다.

다음으로 스프링 컨테이너가 인스턴스 팩터리 메서드를 호출해서 빈을 인스턴스화하는 방법을 알아보자.

인스턴스 팩터리 메서드를 이용한 빈 인스턴스화

다음 예제에서 FixedDepositDaoFactory 클래스는 FixedDepositDao의 인스턴스를 생성하고 반환

하는 인스턴스 팩터리 메서드를 정의한다.

예제 2-7: FixedDepositDaoFactory 클래스

public class FixedDepositDaoFactory {

public FixedDepositDaoFactory() {

}

public FixedDepositDao getFixedDepositDao(String daoType) {

FixedDepositDao fixedDepositDao = null;

if("jdbc".equalsIgnoreCase(daoType)) {

fixedDepositDao = new FixedDepositJdbcDao();

}

if("hibernate".equalsIgnoreCase(daoType)) {

fixedDepositDao = new FixedDepositHiberateDao();

}

.....

return fixedDepositDao;

}

}

56 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

클래스가 인스턴스 팩터리 메서드를 정의하는 경우 public 생성자를 정의해야 스프링 컨테이너가 해

당 클래스의 인스턴스를 생성할 수 있다. 이 예제에서 FixedDepositDaoFactory 클래스는 인자가

없는 public 생성자를 정의했다. FixedDepositDaoFactory의 getFixedDepositDao 메서드는

FixedDepositDao의 인스턴스를 생성하고 반환하는 인스턴스 팩터리 메서드다.

다음 구성 예제에서는 FixedDepositDaoFactory의 getFixedDepositDao 메서드를 호출해

FixedDepositDao의 인스턴스를 얻도록 스프링 컨테이너에 지시한다.

예제 2-8: FixedDepositDaoFactory의 getFixedDepositDao 메서드를 호출하는 구성

<bean id="daoFactory" class="sample.spring.chapter02.basicapp.FixedDepositDaoFactory" />

<bean id="dao" factory-bean="daoFactory" factory-method="getFixedDepositDao">

<constructor-arg index="0" value="jdbc"/>

</bean>

<bean id="service" class="sample.spring.chapter02.bankapp.FixedDepositServiceImpl">

<property name="fixedDepositDao" ref="dao" />

</bean>

이 예제에서 FixedDepositDaoFactory 클래스(인스턴스 팩터리 메서드를 포함하는 클래스)는 일

반 스프링 빈처럼 구성했고 인스턴스 팩터리 메서드의 세부 사항을 구성하는 데는 별도의 <bean> 요

소와 <bean> 요소의 factory-bean 및 factory-method 특성을 사용했다. 여기서 factory-bean

특성에는 인스턴스 팩터리 메서드를 정의하는 빈을 지정하고 factory-method 특성에는 인스턴

스 팩터리 메서드의 이름을 지정한다. 이 예제에서 <property> 요소는 FixedDepositDaoFactory

의 getFixedDepositDao 팩터리 메서드가 반환한 FixedDepositDao의 인스턴스를 Fixed

DepositServiceImpl 인스턴스로 주입한다.

정적 팩터리 메서드와 마찬가지로 <constructor-arg> 요소를 사용해 인스턴스 팩터리 메서드로 인자

를 전달할 수 있다. 중요한 것은 dao 빈을 얻기 위해 ApplicationContext의 getBean 메서드를 호출

하면 FixedDepositDaoFactory의 getFixedDepositDao 팩터리 메서드가 호출된다는 것이다.

지금까지 세터 메서드를 사용해 의존성을 빈으로 주입하는 빈 정의를 알아봤다. 다음으로 다른 DI 메커

니즘으로 의존성을 주입하는 방법을 알아보자.

02. 스프링 프레임워크 기초 57

2-4 의존성 주입 기법

스프링은 빈의 생성자와 세터 메서드의 인자를 사용해 의존성을 주입한다. 정적 또는 인스턴스 팩터리

메서드를 사용해 빈 인스턴스를 생성하는 경우 빈 의존성을 팩터리 메서드로 전달하거나 팩터리 메서드

가 반환한 빈 인스턴스에서 의존성을 설정할 수 있다.

다음으로 다른 DI 기법을 확인해보자.

세터 기반 DI

지금까지 세터 기반 DI의 예를 살펴봤다. 세터 기반 DI에서는 <property> 요소를 사용해 빈 의존성을

지정하는데, <property> 요소는 빈에 필요한 구성 정보(있는 경우)를 전달하는 데도 사용된다.

MyBank 애플리케이션에 고객에게 은행 계좌 명세서 조회, 은행 계좌 내역 확인, 연락처 업데이

트, 비밀번호 변경 및 고객 연락 서비스를 제공하는 PersonalBankingService 클래스가 있다

고 해보자. 이 클래스는 이러한 기능을 제공하기 위해 JmsMessageSender (JMS 메시지 전송),

EmailMessageSender (이메일 전송), WebServiceInvoker (외부 웹 서비스 호출) 객체를 사용한다.

다음 예제는 PersonalBankingService 클래스다.

예제 2-9: PersonalBankingService 클래스

public class PersonalBankingService {

private JmsMessageSender jmsMessageSender;

private EmailMessageSender emailMessageSender;

private WebServiceInvoker webServiceInvoker;

.....

public void setJmsMessageSender(JmsMessageSender jmsMessageSender) {

this.jmsMessageSender = jmsMessageSender;

}

public void setEmailMessageSender(EmailMessageSender emailMessageSender) {

this.emailMessageSender = emailMessageSender;

}

public void setWebServiceInvoker(WebServiceInvoker webServiceInvoker) {

this.webServiceInvoker = webServiceInvoker;

}

.....

}

58 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

이 예제에서 PersonalBankingService 클래스는 JmsMessageSender, EmailMessageSender,

WebServiceInvoker 의존성을 위한 세터 메서드를 정의했다.

다음 예제와 같이 세터 기반 DI를 사용해 PersonalBankingService 클래스의 의존성을 주입할 수 있

다.

예제 2-10: PersonalBankingService 클래스와 그 의존성의 빈 정의

<bean id="personalBankingService" class="PersonalBankingService">

<property name="emailMessageSender" ref="emailMessageSender" />

<property name="jmsMessageSender" ref="jmsMessageSender" />

<property name="webServiceInvoker" ref="webServiceInvoker" />

</bean>

<bean id="jmsMessageSender" class="JmsMessageSender">

.....

</bean>

<bean id="webServiceInvoker" class="WebServiceInvoker" />

.....

</bean>

<bean id="emailMessageSender" class="EmailMessageSender" />

.....

</bean>

personalBankingService 빈 정의에는 PersonalBankingService 클래스의 각 의존성에 해당하는

<property> 요소가 하나씩 있다.

고객이 연락처 번호를 변경하면 PersonalBankingService가 EmailMessageSender 빈을 사용해 고

객의 이메일 주소로 이메일 알림을 보내는데, EmailMessageSender가 이메일 서버에서 인증을 수행하

려면 이메일 서버 주소, 사용자 이름 및 암호가 필요하다. 다음 예제에서 String 형식의 빈 속성을 설정

하는 데도 <property> 요소를 사용했다.

예제 2-11: EmailMessageSender 클래스 및 해당 빈 정의

public class EmailMessageSender {

private String host;

02. 스프링 프레임워크 기초 59

private String username;

private String password;

.....

public void setHost(String host) {

this.host = host;

}

public void setUsername(String username) {

this.username = username;

}

public void setPassword(String password) {

this.password = password;

}

.....

}

<bean id="emailMessageSender" class="EmailMessageSender">

<property name="host" value="smtp.gmail.com"/>

<property name="username" value="myusername"/>

<property name="password" value="mypassword"/>

</bean>

이 예제에서는 <property> 요소로 EmailMessageSender 빈에 필요한 세 속성, 즉 host, username,

password를 설정했다. <property> 요소의 name 특성에는 값을 설정할 빈 속성을 지정하며, value

특성에는 해당 속성의 String 값을 지정한다. 3장에서는 <property> 요소로 기본 형식(예: int, long

등), 컬렉션 형식(예: java.util.List, java.util.Map 등) 및 사용자 지정 형식(예: Address )의 속성을

설정하는 방법을 알아보겠다.

세터 기반 DI를 사용해 정적 및 인스턴스 팩터리 메서드가 생성한 빈으로 의존성을 주입할 수도 있다.

다음으로 세터 기반 DI를 정적 및 인스턴스 팩터리 메서드를 함께 사용하는 방법을 알아보자.

팩터리 메서드가 생성한 빈 인스턴스를 이용한 의존성 주입

세터 기반 DI를 사용해 정적 또는 인스턴스 팩터리 메서드가 반환한 빈 인스턴스로 의존성을 주입할 수

있다.

60 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

다음의 FixedDepositJdbcDao 클래스가 databaseInfo 속성을 정의한다고 가정해보자.

예제 2-12: FixedDepositJdbcDao 클래스

public class FixedDepositJdbcDao {

private DatabaseInfo databaseInfo;

.....

public FixedDepositJdbcDao() { }

public void setDatabaseInfo(DatabaseInfo databaseInfo) {

this. databaseInfo = databaseInfo;

}

.....

}

이 예제에서 databaseInfo 특성은 FixedDepositJdbcDao 클래스의 의존성이며, setDatabaseInfo

메서드는 이 의존성을 처리한다.

다음 예제에서 FixedDepositDaoFactory 클래스는 FixedDepositDaoJdbc 클래스의 인스턴스를 생

성하고 반환하는 팩터리 메서드를 정의한다.

예제 2-13: FixedDepositDaoFactory 클래스

public class FixedDepositDaoFactory {

public FixedDepositDaoFactory() {

}

public FixedDepositDao getFixedDepositDao(String daoType) {

FixedDepositDao fixedDepositDao = null;

if("jdbc".equalsIgnoreCase(daoType)) {

fixedDepositDao = new FixedDepositJdbcDao();

}

if("hibernate".equalsIgnoreCase(daoType)) {

fixedDepositDao = new FixedDepositHiberateDao();

}

.....

02. 스프링 프레임워크 기초 61

return fixedDepositDao;

}

}

이 예제에서 getFixedDepositDao 메서드는 FixedDepositDao 인스턴스를 생성하는 인

스턴스 팩터리 메서드다. getFixedDepositDao 메서드는 daoType 인자 값이 jdbc일 경우

FixedDepositJdbcDao의 인스턴스를 생성한다. 여기서 getFixedDepositDao 메서드는 Fixed

DepositJdbcDao 인스턴스의 databaseInfo 속성을 설정하지 않았다는 데 주의하자.

다음 빈 정의는 예제 2-8에 나온 것처럼 FixedDepositDaoFactory 클래스의 getFixedDepositDao

인스턴스 팩터리 메서드를 호출해 FixedDepositJdbcDao의 인스턴스를 생성하도록 스프링 컨테이너

에 지시한다.

예제 2-14: FixedDepositDaoFactory의 getFixedDepositDao 메서드를 호출하는 구성

<bean id="daoFactory" class="FixedDepositDaoFactory" />

<bean id="dao" factory-bean="daoFactory" factory-method="getFixedDepositDao">

<constructor-arg index="0" value="jdbc"/>

</bean>

이 dao 빈 정의에서는 FixedDepositDaoFactory의 getFixedDepositDao 메서드를 호출

해 FixedDepositJdbcDao의 인스턴스를 생성하고 반환하게 했고 FixedDepositJdbcDao의

databaseInfo 속성을 설정하지는 않았다. databaseInfo 의존성을 설정하려면 다음 예제와 같이

getFixedDepositDao 메서드가 반환한 FixedDepositJdbcDao 인스턴스에서 세터 기반 DI를 수행

할 수 있다.

예제 2-15: FixedDepositDaoFactory의 getFixedDepositDao 메서드를 호출해서 반환된 FixedDepositJdbcDao 인스턴

스에서 databaseInfo 속성을 설정하는 구성

<bean id="daoFactory" class="FixedDepositDaoFactory" />

<bean id="dao" factory-bean="daoFactory" factory-method="getFixedDepositDao">

<constructor-arg index="0" value="jdbc"/>

<property name="databaseInfo" ref="databaseInfo"/>

62 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

</bean>

<bean id="databaseInfo" class="DatabaseInfo" />

이 빈 정의에서는 <property> 요소를 사용해 getFixedDepositDao 인스턴스 팩터리 메서드가 반환한

FixedDepositJdbcDao 인스턴스에서 databaseInfo 속성을 설정한다. 인스턴스 팩터리 메서드와 마

찬가지로 정적 팩터리 메서드가 반환한 빈 인스턴스로 의존성을 주입하는 데도 <property> 요소를 사

용할 수 있다.

다음으로 생성자 인자를 사용해서 빈 의존성을 주입하는 방법을 알아보자.

생성자 기반 DI

생성자 기반 DI에서는 빈의 의존성을 빈 클래스 생성자의 인자로 전달한다. 예를 들어, 다음 예제에

서 PersonalBankingService 클래스의 생성자는 JmsMessageSender, EmailMessageSender,

WebServiceInvoker 객체를 받는다.

예제 2-16: PersonalBankingService 클래스

public class PersonalBankingService {

private JmsMessageSender jmsMessageSender;

private EmailMessageSender emailMessageSender;

private WebServiceInvoker webServiceInvoker;

.....

public PersonalBankingService(JmsMessageSender jmsMessageSender,

EmailMessageSender emailMessageSender,

WebServiceInvoker webServiceInvoker) {

this.jmsMessageSender = jmsMessageSender;

this.emailMessageSender = emailMessageSender;

this.webServiceInvoker = webServiceInvoker;

}

.....

}

02. 스프링 프레임워크 기초 63

PersonalBankingService의 생성자로 전달되는 인자는 PersonalBankingService 클래스의 의존성

을 나타낸다. 다음 예제에서는 <constructor-arg> 요소를 통해 PersonalBankingService 인스턴스

의 의존성을 제공하는 방법이 나온다.

예제 2-17: PersonalBankingService 빈 정의

<bean id="personalBankingService" class="PersonalBankingService">

<constructor-arg index="0" ref="jmsMessageSender" />

<constructor-arg index="1" ref="emailMessageSender" />

<constructor-arg index="2" ref="webServiceInvoker" />

</bean>

<bean id="jmsMessageSender" class="JmsMessageSender">

.....

</bean>

<bean id="webServiceInvoker" class="WebServiceInvoker" />

.....

</bean>

<bean id="emailMessageSender" class="EmailMessageSender" />

.....

</bean>

이 예제에서 <constructor-arg> 요소에는 PersonalBankingService 인스턴스로 전달되는 생성자 인

자를 세부적으로 지정한다. index 특성에는 생성자 인자의 인덱스를 지정한다. 예를 들어, index 특성

값이 0인 경우 <constructor-arg> 요소가 생성자의 첫 번째 인자와 연결되며, 값이 1인 경우 두 번째

인자와 연결되는 방식이다. 이전에 다른 예제에서 <property> 요소의 ref 특성을 사용해 빈 참조를 전

달했었는데, 이와 비슷하게 <constructor-arg> 요소의 ref 특성을 사용해 빈 참조를 전달할 수 있다.

<property> 요소와 마찬가지로 <constructor-arg> 요소를 사용해 빈에 필요한 구성 정보(있는 경우)

를 전달할 수도 있다.

<constructor-arg> 요소는 빈 인스턴스를 생성하는 정적 및 인스턴스 팩터리 메서드로 인자를 전달하

는 데도 사용된다(2-3절 참조).

64 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

빈 참조를 설정하는 데는 <property> 및 <constructor-arg> 요소의 ref 특성을 사용하는 방법 외에도 <property> 및

<constructor-arg> 요소 안에서 <ref> 요소를 사용하는 방법도 있지만, ref 특성을 사용하는 것이 XML을 간결하게 작성

하는 데 도움이 된다.

다음 예제의 EmailMessageSender 클래스 및 해당 빈 정의에서는 <constructor-arg> 요소를 사용해

String 형식의 생성자 인자에 값을 지정하는 방법을 볼 수 있다.

예제 2-18: EmailMessageSender 클래스 및 해당 빈 정의

public class EmailMessageSender {

private String host;

private String username;

private String password;

.....

public EmailMessageSender(String host, String username, String password) {

this.host = host;

this.username = username;

this.password = password;

}

.....

}

<bean id="emailMessageSender" class="EmailMessageSender">

<constructor-arg index="0" value="smtp.gmail.com"/>

<constructor-arg index="1" value="myusername"/>

<constructor-arg index="2" value="mypassword"/>

</bean>

지금까지 <constructor-arg> 요소를 사용해 의존성을 주입하는 방법과 String 형식의 생성자 인자

로 값을 전달하는 방법을 알아봤다. 3장에서는 <constructor-arg> 요소를 사용해 기본 형식(예: int,

long 등), 컬렉션 형식(예: java.util.List, java.util.Map 등) 및 사용자 지정 형식(예: Address ) 속성

을 설정하는 방법을 알아보겠다.

다음으로 생성자 기반 DI와 세터 기반 DI를 함께 사용하는 방법을 알아보자.

02. 스프링 프레임워크 기초 65

생성자 기반 DI와 세터 기반 DI를 함께 사용하는 방법

하나의 빈 클래스에 생성자 기반 DI와 세터 기반 DI가 모두 필요한 경우 <constructor-arg> 및

<property> 요소를 함께 사용해 의존성을 주입할 수 있다.

다음 예제에서는 생성자와 세터 메서드의 인자를 사용해 빈 클래스의 의존성을 주입한다.

예제 2-19: PersonalBankingService 클래스

public class PersonalBankingService {

private JmsMessageSender jmsMessageSender;

private EmailMessageSender emailMessageSender;

private WebServiceInvoker webServiceInvoker;

.....

public PersonalBankingService(JmsMessageSender jmsMessageSender,

EmailMessageSender emailMessageSender) {

this.jmsMessageSender = jmsMessageSender;

this.emailMessageSender = emailMessageSender;

}

public void setWebServiceInvoker(WebServiceInvoker webServiceInvoker) {

this.webServiceInvoker = webServiceInvoker;

}

.....

}

이 예제에서 PersonalBankingService 클래스의 jmsMessageSender 및 emailMessageSender 의

존성은 생성자 인자를 통해 주입되고, webServiceInvoker 의존성은 setWebServiceInvoker 세터

메서드를 통해 주입된다. 다음 빈 정의에서는 <constructor-arg> 및 <property> 요소를 함께 사용해

서 PersonalBankingService 클래스의 의존성을 주입한다.

예제 2-20: 생성자 기반 DI와 세터 기반 DI를 함께 사용

<bean id="dataSource" class="PersonalBankingService">

<constructor-arg index="0" ref="jmsMessageSender" />

<constructor-arg index="1" ref="emailMessageSender" />

<property name="webServiceInvoker" ref="webServiceInvoker" />

</bean>

66 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

지금까지 빈을 생성하고 의존성을 주입하도록 스프링 컨테이너에 지시하는 방법을 알아봤다. 다음으로

빈의 범위에 대해 알아보자.

2-5 빈의 범위

빈의 범위를 지정하면 빈의 인스턴스를 한 번만 생성하고 공유할지(싱글톤 범위), 아니면 빈을 요청할

때마다 새로운 빈 인스턴스를 생성할지(프로토타입 범위) 결정할 수 있다. 빈의 범위는 <bean> 요소의

scope 특성으로 정의하며, scope 특성을 지정하지 않으면 기본적으로 싱글톤 범위 빈이 된다.

웹 애플리케이션에서는 요청, 세션 및 전역 세션이라는 세 가지 범위를 추가로 사용할 수 있다. 이러한 빈의 범위는 빈

인스턴스의 수명을 결정한다. 예를 들어, 요청 범위의 빈은 수명이 단일 HTTP 요청으로 제한된다. 이 장에서는 스프링

웹 MVC나 스프링 포틀릿 MVC에 대해서는 다루지 않으므로 싱글톤과 프로토타입 범위에 대해서만 설명한다. 요청, 세

션 및 전역 세션 범위에 대해서는 10장에서 알아본다.

예제 프로젝트: chapter 2/ch02-bankapp-scopes (이 프로젝트는 싱글톤 및 프로토타입 빈 범위를 사용하는 방법을

보여준다. 애플리케이션을 실행하려면 이 프로젝트에서 BankApp 클래스의 main 메서드를 실행한다. 이 프로젝트에는

실행 가능한 JUnit 테스트 두 개(PrototypeTest, SingletonTest)도 포함돼 있다.)

싱글톤

싱글톤 범위는 애플리케이션 컨텍스트 XML 파일에서 정의되는 모든 빈의 기본 범위다. 싱글톤 범위 빈

의 인스턴스는 스프링 컨테이너가 생성될 때 생성되고, 스프링 컨테이너가 삭제될 때 함께 삭제된다. 스

프링 컨테이너는 싱글톤 범위 빈의 인스턴스를 하나만 생성하고 이에 의존하는 모든 빈에 이 인스턴스를

공유한다.

다음 예제에서 ch02-bankapp-scopes 프로젝트의 applicationContext.xml 파일에 있는 모든 빈

은 싱글톤 범위 빈이다.

예제 2-21: applicationContext.xml - 싱글톤 범위 빈

프로젝트: ch02-bankapp-scopes,

소스 위치: src/main/resources/META-INF/spring

<beans ..... >

02. 스프링 프레임워크 기초 67

<bean id="controller"

class="sample.spring.chapter02.bankapp.controller.FixedDepositControllerImpl">

<property name="fixedDepositService" ref="service" />

</bean>

<bean id="service"

class="sample.spring.chapter02.bankapp.service.FixedDepositServiceImpl">

<property name="fixedDepositDao" ref="dao" />

</bean>

<bean id="dao" class="sample.spring.chapter02.bankapp.dao.FixedDepositDaoImpl" />

.....

</beans>

이 applicationContext.xml 파일에서 controller, service, dao 빈은 <bean> 요소에 scope 특성

을 지정하지 않았으므로 싱글톤 범위가 된다. 즉, 스프링 컨테이너는 FixedDepositControllerImpl,

FixedDepositServiceImpl, FixedDepositDaoImpl 클래스의 인스턴스를 하나만 생성한다. 이러한

빈은 싱글톤 범위이므로 ApplicationContext의 getBean 메서드로 빈의 인스턴스를 가져올 때 스프링

컨테이너는 동일한 인스턴스를 반환한다.

scope 특성을 지정하지 않거나 scope 특성을 singleton으로 지정하면 빈이 싱글톤 범위가 된다.

다음 예제에는 ch02-bankapp-scopes 프로젝트에 포함된 SingletonTest 클래스(JUnit 테스트 클

래스)의 testInstances 메서드가 나온다. testInstances 메서드는 ApplicationContext의 getBean

메서드를 여러 번 호출하고 controller 빈의 동일한 인스턴스를 반환되는지 여부를 테스트한다.

예제 2-22: SingletonTest JUnit 테스트 클래스

프로젝트: ch02-bankapp-scopes,

소스 위치: src/test/java/sample/spring/chapter02/bankapp

package sample.spring.chapter02.bankapp;

import static org.junit.Assert.assertSame;

import org.junit.BeforeClass;

68 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

import org.junit.Test;

import sample.spring.chapter02.bankapp.controller.FixedDepositController;

public class SingletonTest {

private static ApplicationContext context;

@BeforeClass

public static void init() {

context = new ClassPathXmlApplicationContext(

"classpath:META-INF/spring/applicationContext.xml");

}

@Test

public void testInstances() {

FixedDepositController controller1 = (FixedDepositController) context.

getBean("controller");

FixedDepositController controller2 = (FixedDepositController) context.

getBean("controller");

assertSame("Different FixedDepositController instances", controller1, controller2);

}

.....

}

이 예제에서 JUnit의 @BeforeClass 어노테이션은 init 메서드를 클래스의 다른 테스트 메서드(즉,

JUnit의 @Test 어노테이션이 지정된 메서드)보다 먼저 호출하게 한다. 즉, @BeforeClass 어노테이

션이 지정된 메서드는 한 번만 호출되며, 그다음 @Test 어노테이션이 지정된 메서드가 호출된다. 이

예제의 init 메서드는 정적 메서드라는 데 주의해야 한다. init 메서드는 구성 메타데이터(예제 2-21 )

를 ClassPathXmlApplicationContext의 생성자로 전달해서 ApplicationContext 객체의 인스턴

스를 생성한다. testInstances 메서드는 controller 빈의 인스턴스 두 개를 얻고 JUnit의 assertSame

단정문으로 두 인스턴스가 동일한지 확인한다. controller 빈은 싱글톤 범위이므로 controller1 및

controller2 빈 인스턴스는 동일하다. 따라서 SingletonTest의 testInstances 테스트는 단정 오류 없

이 실행된다.

다음 그림은 ApplicationContext의 getBean 메서드를 여러 번 호출하더라도 스프링 컨테이너가

controller 빈의 동일한 인스턴스를 반환한다는 것을 보여준다.

02. 스프링 프레임워크 기초 69

스프링 컨테이너

빈 이름

빈 형식

그림 2-4 싱글톤 범위 빈을 여러 번 요청하더라도 스프링 컨테이너는 동일한 빈 인스턴스를 반환한다.

이 그림에서 controller 빈을 여러 번 요청하더라도 controller 빈의 동일한 인스턴스가 반환된다는 것

을 알 수 있다.

그림 2-4에서 controller 빈 인스턴스는 2칸짜리 사각형으로 표시된다. 위쪽 칸은 빈의 이름(<bean> 요소의 id 특성 값)

이고 아래쪽 칸은 빈의 형식(<bean> 요소의 class 특성 값)이다. 이 책의 나머지 부분에서도 이 표기법으로 스프링 컨테

이너 내의 빈 인스턴스를 표시한다.

싱글톤 범위 인스턴스는 이에 의존하는 모든 빈에 공유된다. 다음 예제에 나오는 SingletonTest

JUnit 테스트 클래스의 testReference 메서드는 FixedDepositController 인스턴스가 참조하는

FixedDepositDao 인스턴스가 ApplicationContext의 getBean 메서드를 직접 호출해서 얻은 인스

턴스와 동일한지 확인한다.

예제 2-23: SingletonTest JUnit 테스트 클래스의 testReference 메서드

프로젝트: ch02-bankapp-scopes,

소스 위치: src/test/java/sample/spring/chapter02/bankapp

package sample.spring.chapter02.bankapp;

import static org.junit.Assert.assertSame;

import org.junit.Test;

public class SingletonTest {

private static ApplicationContext context;

.....

@Test

public void testReference() {

FixedDepositController controller = (FixedDepositController) context.

getBean("controller");

FixedDepositDao fixedDepositDao1 =

controller.getFixedDepositService().getFixedDepositDao();

FixedDepositDao fixedDepositDao2 = (FixedDepositDao) context.getBean("dao");

assertSame("Different FixedDepositDao instances", fixedDepositDao1, fixedDepositDao2);

}

}

이 예제에서 testReference 메서드는 먼저 FixedDepositController 빈이 참조하는 FixedDepositDao

인스턴스(예제의 fixedDepositDao1 변수)를 얻은 다음, 직접 ApplicationContext의 getBean 메

서드를 사용해 FixedDepositDao 빈의 다른 인스턴스(예제의 fixedDepositDao2 변수)를 얻었다.

fixedDepositDao1과 fixedDepositDao2 인스턴스는 동일하므로 testReference 테스트는 정상적으

로 실행된다.

그림 2-5는 FixedDepositController 인스턴스가 참조하는 FixedDepositDao 인스턴스와

ApplicationContext의 getBean ("dao") 메서드를 호출해서 얻은 인스턴스가 같다는 것을 보여준다.

FixedDepositControllerImpl이 참조하는

FixedDepositDaoImpl

스프링 컨테이너

그림 2-5 싱글톤 범위 인스턴스는 이에 의존하는 모든 빈에 공유된다.

02. 스프링 프레임워크 기초 71

이 그림에서 FixedDepositController 빈 인스턴스가 참조하는 FixedDepositDao 인스턴스와

ApplicationContext의 getBean을 직접 호출해서 얻은 인스턴스는 같다. 여러 빈이 싱글톤 범위 빈에

의존하는 경우 모든 의존 빈이 동일한 싱글톤 범위 빈의 인스턴스를 공유한다.

다음으로 여러 스프링 빈 컨테이너 간에 동일한 싱글톤 범위 빈이 공유되는지 여부를 확인해보자.

싱글톤 범위 빈과 여러 스프링 컨테이너 인스턴스

싱글톤 범위 빈 인스턴스의 범위는 스프링 컨테이너 인스턴스로 제한된다. 즉, 동일한 구성 메타데이터

를 사용해 스프링 컨테이너의 인스턴스 두 개를 만드는 경우 각 스프링 컨테이너는 각기 다른 싱글톤 범

위 빈의 인스턴스를 가진다.

다음 예제에서 SingletonTest 클래스의 testSingletonScope 메서드는 두 개의 서로 다른 스프링 컨테

이너 인스턴스에서 가져온 FixedDepositController 빈 인스턴스가 동일한지 확인한다.

예제 2-24: SingletonTest JUnit 테스트 클래스의 testSingletonScope 메서드

프로젝트: ch02-bankapp-scopes,

소스 위치: src/test/java/sample/spring/chapter02/bankapp

package sample.spring.chapter02.bankapp;

import static org.junit.Assert.assertNotSame;

public class SingletonTest {

private static ApplicationContext context;

.....

@BeforeClass

public static void init() {

context = new ClassPathXmlApplicationContext(

"classpath:META-INF/spring/applicationContext.xml");

}

@Test

public void testSingletonScope() {

ApplicationContext anotherContext = new ClassPathXmlApplicationContext(

"classpath:META-INF/spring/applicationContext.xml");

72 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

FixedDepositController fixedDepositController1 =

(FixedDepositController) anotherContext.getBean("controller");

FixedDepositController fixedDepositController2 =

(FixedDepositController) context .getBean("controller");

assertNotSame("Same FixedDepositController instances",

fixedDepositController1, fixedDepositController2);

}

}

SingletonTest의 init 메서드(JUnit의 @BeforeClass 어노테이션 지정)는 @Test 어노테이션을 지

정한 다른 메서드가 실행되기 전에 ApplicationContext (context 변수로 지정)의 인스턴스를 생성

한다. testSingletonScope 메서드는 동일한 applicationContext.xml 파일을 사용해 스프링 컨테이

너(anotherContext 변수로 지정)의 인스턴스를 하나 더 생성한다. 그리고 두 스프링 컨테이너에서

FixedDepositController 빈의 인스턴스를 가져온 다음 인스턴스가 동일한지 확인한다. context 인스

턴스에서 가져온 FixedDepositController 인스턴스와 anotherContext 인스턴스에서 가져온 인스턴

스는 서로 다르므로 testSingletonScope 테스트는 정상적으로 실행된다.

다음 그림은 testSingletonScope 메서드가 수행하는 작업을 도식화해서 보여준다.

스프링 컨테이너(context)

스프링 컨테이너(anotherContext)

범위가 스프링 IoC 컨테이너로

제한되므로 각기 다른 controller

인스턴스가 생성된다.

그림 2-6 각 스프링 컨테이너가 싱글톤 범위 빈의 인스턴스를 별도로 생성한다.

02. 스프링 프레임워크 기초 73

이 그림에서 각 스프링 컨테이너가 controller 빈의 인스턴스를 별도로 생성했음을 알 수 있다. 따라

서 getBean ("controller") 메서드를 호출하면 context 및 anotherContext 인스턴스는 각기 다른

controller 빈의 인스턴스를 반환한다.

testSingletonScope 메서드는 각 스프링 컨테이너가 싱글톤 범위 빈의 인스턴스를 별도로 생성한다는

것을 보여준다. 또한 스프링 컨테이너는 각 빈 정의에 해당하는 싱글톤 범위 빈의 인스턴스를 생성한다

는 데 주의하자. 다음 예제에는 FixedDepositDaoImpl 클래스의 빈 정의가 두 번 나온다.

예제 2-25: applicationContext.xml - 동일한 클래스의 빈을 두 번 정의하는 예

프로젝트: ch02-bankapp-scopes,

소스 위치: src/main/resources/META-INF/spring

<bean id="dao" class="sample.spring.chapter02.bankapp.dao.FixedDepositDaoImpl" />

<bean id="anotherDao"

class="sample.spring.chapter02.bankapp.dao.FixedDepositDaoImpl" />

이 예제에서는 FixedDepositDaoImpl 클래스의 빈을 두 번 정의했고, scope 특성은 지정하

지 않았으므로 싱글톤 범위 빈으로 정의했다. 한 클래스의 빈을 여러 번 정의하면 스프링 컨테이너

는 매번 빈 인스턴스를 생성한다. 즉, 스프링 컨테이너는 dao와 anotherDao 빈 정의에 대해 별

도의 FixedDepositDaoImpl 클래스 인스턴스를 생성한다. 다음 예제에서 SingletonScope

의 testSingletonScopePerBeanDef 메서드는 dao 및 anotherDao 빈 정의에 해당하는

FixedDepositDaoImpl 인스턴스가 동일한지 확인한다.

예제 2-26 – SingletonTest JUnit 테스트 클래스의 testSingletonScopePerBeanDef 메서드

프로젝트: ch02-bankapp-scopes,

소스 위치: src/test/java/sample/spring/chapter02/bankapp

package sample.spring.chapter02.bankapp;

import static org.junit.Assert.assertNotSame;

public class SingletonTest {

private static ApplicationContext context;

.....

74 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

@Test

public void testSingletonScopePerBeanDef() {

FixedDepositDao fixedDepositDao1 = (FixedDepositDao) context.getBean("dao");

FixedDepositDao fixedDepositDao2 = (FixedDepositDao) context.getBean("anotherDao");

assertNotSame("Same FixedDepositDao instances", fixedDepositDao1, fixedDepositDao2);

}

}

이 예제에서 fixedDepositDao1 및 fixedDepositDao2 변수는 스프링 컨테이너가 각각 dao 및

anotherDao 빈 정의에 따라 생성한 FixedDepositDaoImpl 클래스의 인스턴스를 나타낸다.

testSingleScopePerBeanDef 테스트를 실행하면 fixedDepositDao1 인스턴스(dao 빈 정의와 연

결)와 fixedDepositDao2 인스턴스(anotherDao 빈 정의와 연결)가 서로 다르므로 단정 오류 없이

정상적으로 실행된다.

다음 그림은 빈 정의마다 별도의 싱글톤 범위 빈이 생성된다는 것을 보여준다.

스프링 컨테이너

그림 2-7 빈 정의마다 별도의 싱글톤 범위 빈 인스턴스가 생성된다.

이 그림을 보면 스프링 컨테이너 내에 빈 정의마다 별도의 싱글톤 범위 빈 인스턴스가 있음을 알 수 있

다.

앞에서 싱글톤 범위 빈은 기본적으로 사전 인스턴스화되므로 스프링 컨테이너의 인스턴스가 생성될 때

싱글톤 범위 빈의 인스턴스도 함께 생성된다고 설명한 바 있다. 다음으로 싱글톤 범위 빈을 지연 초기화

하는 방법을 알아보자.

02. 스프링 프레임워크 기초 75

싱글톤 범위 빈의 지연 초기화

싱글톤 범위 빈의 인스턴스를 처음 요청받을 때 생성하도록 스프링 컨테이너에 지시할 수 있다. 다음 빈

정의에는 lazyBean 빈을 지연 초기화하도록 스프링 컨테이너에 지시하는 방법이 나온다.

예제 2-27: 싱글톤 범위 빈의 지연 초기화

<bean id="lazyBean" class="example.LazyBean" lazy-init="true"/>

<bean> 요소의 lazy-init 특성에는 빈 인스턴스를 지연 생성 또는 사전 생성하도록 지정한다. 이 예제

와 같이 특성 값이 true인 경우 스프링 컨테이너는 빈이 처음 요청될 때 빈 인스턴스를 초기화한다.

다음 순서도는 lazy-init 특성에 따라 싱글톤 범위 빈 인스턴스의 생성 시점이 어떻게 달라지는지 보여

준다.

애플리케이션

스프링 컨테이너생성

생성

생성

그림 2-8 지연 초기화되는 싱글톤 범위 빈 인스턴스는 처음 요청될 때 생성된다.

이 다이어그램에서 BeanA 및 LazyBean은 각각 사전 초기화 및 지연 초기화로 설정된 싱글톤 범

위 빈 인스턴스다. BeanA는 사전 초기화로 설정됐으므로 스프링 컨테이너 인스턴스가 생성될 때

함께 초기화된다. 반면 LazyBean은 스프링 컨테이너에서 LazyBean의 인스턴스를 얻기 위해

ApplicationContext의 getBean 메서드를 처음 호출할 때 인스턴스화된다.

76 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

<beans> 요소의 default-lazy-init 특성을 사용하면 애플리케이션 컨텍스트 XML 파일에 있는 빈 정의에 적용할 기본

초기화 전략을 지정할 수 있다. <bean> 요소의 lazy-init 특성 값이 <beans> 요소의 default-lazy-init 특성 값과 다른 경

우 lazy-init 특성이 빈에 적용된다.

그렇다면 싱글톤 범위 빈은 사전 초기화 및 지연 초기화 중 어떤 방식으로 초기화하는 것이 좋을까? 대

부분의 애플리케이션에서는 스프링 컨테이너를 생성할 때 구성 문제를 미리 발견할 수 있는 사전 초기화

방식이 좋다. 다음 예제의 aBean은 지연 초기화되며 bBean 빈에 의존하는 싱글톤 범위 빈이다.

예제 2-28: 지연 초기화되는 싱글톤 범위 빈

public class ABean {

private BBean bBean;

public void setBBean(BBean bBean) {

this.bBean = bBean;

}

.....

}

<bean id="aBean" class="ABean" lazy-init="true">

<property name="bBean" value="bBean" />

</bean>

<bean id="bBean" class="BBean"/>

이 예제에서 ABean의 bBean 속성은 BBean 빈을 참조한다. 그런데 <property> 요소에서 ref 특성이

아닌 value 특성으로 ABean의 bBean 속성을 설정했다. 문제는 빈 정의를 포함하는 XML 파일을 전달

하고 ApplicationContext 인스턴스를 생성해도 오류가 보고되지 않는다는 점이다. 대신 aBean 빈을

가져오기 위해 ApplicationContext의 getBean 메서드를 호출하면 다음과 같은 오류 메시지가 출력된

다.

Caused by: java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to

required type [BBean] for property ‘bBean: no matching editors or conversion strategy found

02. 스프링 프레임워크 기초 77

이 오류 메시지가 발생하는 이유는 스프링 컨테이너가 ABean의 bBean 속성에 있는 String 값

을 BBean 형식으로 변환할 수 없기 때문이다. 즉, <bean> 요소의 ref 특성 대신 value 특성

을 지정한 간단한 구성 문제다. aBean 빈을 사전 인스턴스화로 설정했다면(지연 초기화 대신)

ApplicationContext에서 aBean 빈 인스턴스를 얻으려고 할 때가 아니라 ApplicationContext의 인

스턴스를 만들 때 이 구성 문제가 발견됐을 것이다.

다음으로 스프링의 프로토타입 범위 빈에 대해 알아보자.

프로토타입

프로토타입 범위 빈은 스프링 컨테이너가 항상 새로운 인스턴스를 반환한다는 점에서 싱글톤 범위 빈과

차이가 있다. 프로토타입 범위 빈의 다른 고유한 특징은 항상 지연 인스턴스화된다는 것이다.

ch02-bankapp-scopes 프로젝트의 applicationContext.xml 파일에 있는 FixedDepositDetails

빈은 프로토타입 범위 빈이다.

예제 2-29: applicationContext.xml - 프로토타입 범위 빈의 예

프로젝트: ch02-bankapp-scopes

소스 위치: src/main/resources/META-INF/spring

<bean id="fixedDepositDetails"

class="sample.spring.chapter02.bankapp.domain.FixedDepositDetails"

scope="prototype" />

이 예제에서는 <bean> 요소의 scope 특성 값을 prototype으로 설정해 FixedDepositDetails 빈을

프로토타입 범위 빈으로 지정했다.

다음 예제에서 PrototypeTest JUnit 테스트 클래스의 testInstances 메서드는 스프링 컨테이너에서

얻은 FixedDepositDetails 빈의 인스턴스 두 개가 서로 다르다는 것을 보여준다.

78 시작하세요! 스프링 4 프로그래밍: 스프링 코어부터 웹 MVC, 스프링 시큐리티까지

예제 2-30: PrototypeTest JUnit 테스트 클래스의 testInstances 메서드

프로젝트: ch02-bankapp-scopes,

소스 위치: src/test/java/sample/spring/chapter02/bankapp

package sample.spring.chapter02.bankapp;

import static org.junit.Assert.assertNotSame;

public class PrototypeTest {

private static ApplicationContext context;

.....

@Test

public void testInstances() {

FixedDepositDetails fixedDepositDetails1 =

(FixedDepositDetails)context.getBean("fixedDepositDetails");

FixedDepositDetails fixedDepositDetails2 =

(FixedDepositDetails) context.getBean("fixedDepositDetails");

assertNotSame("Same FixedDepositDetails instances",

fixedDepositDetails1, fixedDepositDetails2);

}

}

testInstances 테스트를 실행해보면 ApplicationContext에서 얻은 FixedDepositDetails의 두 인스

턴스(fixedDepositDetails1 및 fixedDepositDetails2 )가 서로 다르기 때문에 단정 오류 없이 정상

적으로 실행된다.

다음으로 빈의 올바른 범위(싱글톤 또는 프로토타입)를 선택하는 방법을 정리해보자.

빈의 올바른 범위 선택

빈이 대화 상태(conversational state )를 유지하지 않는 경우(즉, 상태 비저장형(stateless )인 경

우) 싱글톤 범위 빈으로 정의해야 한다. 반면 빈이 대화 상태를 유지하는 경우 프로토타입 범위 빈으로

정의해야 한다. MyBank 애플리케이션에서 FixedDepositServiceImpl, FixedDepositDaoImpl,

FixedDepositControllerImpl 빈은 기본적으로 상태 비저장이므로 싱글톤 범위 빈으로 정의했다. 이

02. 스프링 프레임워크 기초 79

와 달리 MyBank 애플리케이션에서 도메인 객체인 FixedDepositDetails 빈은 대화 상태를 유지하므

로 프로토타입 범위 빈으로 정의했다.

도메인 객체는 애플리케이션에서 ORM 프레임워크(예: 하이버네이트 또는 iBATIS)를 사용하는 경우 ORM 프레임워

크에서 생성하거나 애플리케이션 코드에서 new 연산자를 사용해 프로그래밍 방식으로 생성한다. 애플리케이션에서

ORM 프레임워크로 영속성을 구현하는 경우 도메인 객체를 애플리케이션 컨텍스트 XML 파일에 정의하지 않는 것은

이 때문이다.

2-6 요약

2장에서는 스프링 프레임워크의 몇 가지 기본 개념을 다뤘다. 인터페이스 기반 프로그래밍 설계 방법,

빈 인스턴스를 생성하는 다른 방법, 생성자 기반 ID, 그리고 빈의 범위에 대해 알아봤다. 3장에서는 생

성자 인자와 빈 속성의 다른 형식(예: int, long, Map, Set 등)을 설정하는 방법을 알아본다.