Jint 2022. 11. 11. 23:38

이번 절에서는 컴포넌트 스캔과 어노테이션을 이용해 빈을 자동 등록하는 방법을 배워본다. 방법은 다음과 같다.

1) 빈 생성 대상이 되는 클래스에 @Component 어노테이션으로 표시를 한다.

2) 스프링 IoC 컨테이너는 @Component가 붙은 클래스를 찾아 빈을 생성한다.

스프링에서는 @Component 외에 클래스를 관리하고 이해하는데 도움을 주기 위해 클래스의 역할에 따라 붙일 수 있는 어노테이션을 추가로 제공한다. 다음 표는 빈 생성 대상 클래스임을 표시할 때 붙일 수 있는 어노테이션 목록, 즉 자동으로 생성할 빈을 지정하는 어노테이션 목록이다.

어노테이션 설명
@Component 빈 생성 대상이 되는 모든 클래스에 대해 붙일 수 있다.
@Repository DAO와 같은 퍼시스턴스(persistence) 역할을 수행하는 클래스에 붙인다.
@Service 서비스 역할을 수행하는 클래스에 붙인다.
@Controller MVC 구조에서 Controller 역할을 수행하는 클래스에 붙인다.

앞의 표에 제공하는 어노테이션 중에서 어떤 것을 붙이더라도 상관 없다. 그러나 이왕이면 클래스의 역할에 따라 알맞은 어노테이션을 붙인다면 나중에 코드를 해석하고 이해하는데 도움이 될 것이다. 또한, 특정 어노테이션이 붙은 클래스만 선별하여 어떤 작업을 하고자 할 때 유용하다.

 

1. @Component가 붙은 클래스를 자동으로 찾기

@Component 사용을 실습해 본다.

 

- 실습 패키지 생성

exam 패키지 아래에 test21 패키지를 생성한다. test20 패키지의 모든 파일을 복사해온다.

 

- @Component 표시하기

빈을 생성할 클래스는 모두 @Component를 붙인다. 이번 실습은 Car 클래스와 Engine 클래스를 가지고 테스트 한다.

exam.test21.Car 클래스를 열고, 클래스 선언 앞에 @Component를 붙인다.

package exam.test21;

import java.util.Map;

//import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component("car")
public class Car {
	
	...
	
	//@Resource(name="kiaEngine")
	@Autowired
	public void setEngine(Engine engine) {
		this.engine = engine;
	}
	
	...
	
}

 

@Component("car")
public class Car {
    ...
}

@Component에 들어가는 속성 값은 빈의 이름이다. getBean() 메서드를 호출할 때 이 이름을 사용한다.

//Resource(name="kiaEngine")

engine 프로퍼티의 값을 특정 객체로 한정하지 않도록 @Resource를 제거한다.

@Autowired
public void setEngine(Engine engine) {
    ...
}

대신 이전에서처럼 @Autowired를 선언하여 engine 프로퍼티의 타입과 일치하는 객체를 찾아 주입하게 한다.

exam.test21.Engine 클래스를 열고, 클래스 선언 앞에 @Component를 붙인다.

package exam.test21;

import org.springframework.stereotype.Component;

@Component("engine")
public class Engine {
    ...
}

 

- beans.xml 빈 설정 파일

exam/test21/beans.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" 
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context.xsd">

	<!-- <context:annotation-config/> -->
	<context:component-scan base-package="exam.test21"/>

</beans>

 

<context:component-scan base-package="exam.test21"/>

<context:component-scan/> 태그를 사용하여 @Component, @Repository 등 빈 생성 표시자(어노테이션)가 붙은 클래스를 검색하라고 선언한다. 클래스 검색을 실시할 대상 패키지를 지정한다. 앞의 코드의 경우 exam.test21 패키지 및 그 하위 패키지를 모두 검색할 것이다.

<!-- <context:annotation-config/> -->

<context:component-scan/> 태그를 선언하면 <context:annotation-config/> 태그의 기능이 자동으로 활성화된다. 따라서 <context:annotation-config/> 태그를 제거한다.

 

- 빈 컨테이너 테스트

@Component가 붙은 빈이 자동으로 생성되었는지 확인해 본다. exam.test21.Test 클래스를 다음과 같이 편집한다.

package exam.test21;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
	
	public static void main(String[] args) {
		//IoC 컨테이너 준비하여 빈 생성
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("exam/test21/beans.xml");
		
		Car car = (Car)ctx.getBean("car");
		Engine engine = (Engine)ctx.getBean("engine");
		engine.setMaker("Hyundai");
		engine.setCc(1997);
		if(car != null) {
			System.out.println("car != null");
		}
		if(engine != null) {
			System.out.println("engine != null");
		}
		System.out.println(car);
	}
	
}

car와 engine의 null 여부를 검사해 보면 정상적으로 인스턴스가 생성되었음을 알 수 있다. 또한, Car 클래스의 engine 프로퍼티에 @Component에 의해 생성된 Engine 객체가 자동 주입되었다는 것을 알 수 있다. 다음은 Test 클래스의 실행 결과이다(그림 1).

그림 1 (exam.test21.Test 클래스 실행 결과)

이렇게 컴포넌트 자동 탐색(<context:component-scan/>)과 빈 자동 생성 표시자(@Component 등)를 이용하면 빈 설정 파일(beans.xml)에 일일이 빈 정보를 선언할 필요가 없어진다.

 

- 컴포넌트 탐색의 포함 조건과 제외 조건

<context:component-scan/> 태그를 사용할 때 다음과 같이 탐색 조건을 추가할 수 있다.

<context:component-scan base-package="exam.test21">
    <context:include-filter type="" expression=""/>
    <context:exclude-filter type="" expression=""/>
</context:component-scan>

context:include-filter 태그는 빈 탐색에 포함할 대상자를 지정할 때 사용한다. context:exclude-filter 태그는 빈 탐색에서 제외할 대상자를 지정할 때 사용한다.

 

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

 

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

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

freelec.co.kr