149. 빈 자동 등록
이번 절에서는 컴포넌트 스캔과 어노테이션을 이용해 빈을 자동 등록하는 방법을 배워본다. 방법은 다음과 같다.
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).
이렇게 컴포넌트 자동 탐색(<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