교재 실습/자바 웹 개발 워크북

132. XML 기반 빈 관리 컨테이너 (2)

Jint 2022. 10. 15. 11:55

2. 스프링 빈 컨테이너 ClassPathXmlApplicationContext 사용

build.gradle 파일에서 스프링 라이브러리를 가져오는 부분을 dependencies 블록에서 더 직관적으로 표현했다.

plugins {
	id 'org.springframework.boot' version '2.3.1.RELEASE'
	id 'io.spring.dependency-management' version '1.0.9.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
	compileOnly {
			extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
	implementation 'org.springframework.boot:spring-boot-starter-security'
	
	//스프링 라이브러리
	implementation 'org.springframework.boot:spring-boot-starter-web'
	implementation 'org.springframework.boot:spring-boot-starter'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	
	implementation 'org.springframework.kafka:spring-kafka'
	compileOnly 'org.projectlombok:lombok'
	runtimeOnly 'com.h2database:h2'
	runtimeOnly 'mysql:mysql-connector-java'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
	testImplementation 'org.springframework.kafka:spring-kafka-test'
	testImplementation 'org.springframework.security:spring-security-test'
}

test {
	useJUnitPlatform()
}

참고링크 : https://linkeverything.github.io/study/springboot/add-library/

 

Gradle 프로젝트에 라이브러리 추가하기

프로그래밍을 하는 데 있어서 라이브러리 라는 용어를 자주 사용하게 됩니다. 라이브러리는 “도서관” 이라는 의미겠지만, coding 에서 의미는 조금 상이합니다. 이번 내용은 Spring boot에 국한되

linkeverything.github.io

 

- 실습 패키지 생성

실습에 사용할 자바 패키지 exam.test01를 생성한다. Gradle 프로젝트의 기본 자바 소스 폴더는 src/main/java 이다. 이 폴더 아래에 패키지 폴더를 생성한다(그림 1).

그림 1 (패키지 생성)

 

- Score 클래스 정의

빈 컨테이너에서 관리할 클래스를 준비한다. 학생의 국어, 영어, 수학 점수를 보관하는 클래스이다. 이렇게 값을 보관하는 용도로 사용하는 클래스를 '값 객체(Value Object)'라고 부른다.

exam.test01 패키지에 Score 클래스를 생성한 뒤 내용은 다음과 같이 작성한다.

package exam.test01;

public class Score {
	
	String name;
	float kor;
	float eng;
	float math;
	
	public Score() {}
	
	public Score(String name, float kor, float eng, float math) {
		this.name = name;
		this.kor = kor;
		this.eng = eng;
		this.math = math;
	}
	
	public float average() {
		return sum() / (float)3;
	}
	
	public float sum() {
		return kor + eng + math;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public float getKor() {
		return kor;
	}
	
	public void setKor(float kor) {
		this.kor = kor;
	}

	public float getEng() {
		return eng;
	}

	public void setEng(float eng) {
		this.eng = eng;
	}

	public float getMath() {
		return math;
	}

	public void setMath(float math) {
		this.math = math;
	}

}

 

- 빈 설정 XML 파일 준비

애플리케이션에서 사용할 객체는 빈 설정 파일에 선언한다. 스프링 IoC 컨테이너는 빈 설정 파일에 선언된 대로 빈을 생성한다.

exam.test01 패키지에 beans.xml 파일을 생성한다. 다음과 같이 XML 파일을 작성한다.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="score" class="exam.test01.Score"/>
    
</beans>
<beans> ... </beans>

빈 설정 파일은 스프링에서 정의한 규칙에 따라 XML 태그를 작성해야 한다. XML 선언을 제외하고 빈 설정 파일에서 제일 먼저 등장하는 태그는 beans이다.

<beans xmlns="http://www.springframework.org/schema/beans">
</beans>

beans 태그는 http://www.springframework.org/schema/beans 네임스페이스에 소속되어 있기 때문에 XML 파서가 이해할 수 있도록 네임스페이스를 밝혀야 한다. 자바 클래스를 사용하기 전에 import를 선언하는 것과 비슷하다.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd">
    
</beans>

그리고 네임스페이스를 정의한 XML 스키마 파일의 위치를 지정한다.

<bean id="score" class="exam.test01.Score"/>

▶ 자바 코드로 표현하면?

new exam.test01.Score();

스프링 IoC 컨테이너가 생성할 자바 빈에 대한 정보는 <bean> 태그로 선언한다. class 속성에는 클래스 이름을 지정한다. 반드시 패키지 이름을 포함한 클래스 이름(fully qualified name)이어야 한다. id 속성은 객체의 식별자이다. 빈 컨테이너에서 객체를 꺼낼 때 이 식별자를 사용한다.

 

- 스프링 IoC 컨테이너 사용

ClassPathXmlApplicationContext 클래스를 사용하여 IoC 컨테이너를 준비한다. IoC 컨테이너는 빈 설정 파일에 선언된 대로 인스턴스를 생성하여 객체 풀(pool)에 보관한다.

exam.test01 패키지에 Test 클래스를 생성하여 다음과 같이 작성한다.

package exam.test01;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {

	public static void main(String[] args) {
		//IoC 컨테이너 준비하여 빈 생성
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("exam/test01/beans.xml");
		//빈 꺼내기
		Score score = (Score)ctx.getBean("score");
		
		System.out.println("합계:" + score.sum());
		System.out.println("평균:" + score.average());
	}
	
}
//IoC 컨테이너 준비하여 빈 생성
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("exam/test01/beans.xml");

ClassPathXmlApplicationContext 클래스의 인스턴스를 생성할 때 생성자에 빈 설정 파일의 경로를 넘긴다. ClassPathXmlApplicationContext 클래스는 자바 클래스 경로에서 exam/test01 폴더를 찾는다. 그리고 beans.xml 파일을 로딩한다. 빈 설정 파일에 선언된 빈을 생성하여 객체 풀(pool)에 보관한다. 현재 예제에서는 Score 객체를 한 개 생성할 것이다(그림 2).

그림 2 (빈 컨테이너의 인스턴스 생성)

//빈 꺼내기
Score score = (Score)ctx.getBean("score");

빈 컨테이너가 준비되었으면 getBean() 메서드를 호출하여 빈을 꺼낸다. getBean() 메서드를 호출할 때 넘겨주는 매개변수 값은 빈 아이디이다(그림 3). 빈 아이디는 빈 설정 파일에 선언되어 있다. getBean() 메서드의 반환 타입은 Object이기 때문에 반환된 객체를 제대로 사용하려면 실제 타입으로 형변환해야 한다.

 

그림 3 (아이디와 getBean() 메서드)

 

- 실행 결과

실행 결과를 확인해 보면 아무런 오류 없이 합계와 평균 값이 출력된다. 정상적으로 Score 객체를 찾아 sum() 메서드와 average() 메서드를 호출하였다. 단 score 객체에 대해 국어, 영어, 수학 점수를 할당하지 않아서 출력 결과가 0.0이 되었다(그림 4).

그림 4 (실행 결과 콘솔)

 

참고도서 : https://freelec.co.kr/book/1674/

 

[열혈강의] 자바 웹 개발 워크북

[열혈강의] 자바 웹 개발 워크북

freelec.co.kr