티스토리 뷰

 각 클래스를 생성하고, 이를 bean 객체로 등록하는 것이 조금 번거로운 작업이라고 생각할 수 있다. 

이번 포스팅은 클래스를 생성하고, @Component 어노테이션을 다는 것만으로 bean 객체를 자동 등록할 수 있는 기법인 component-scan 을 다루려고 한다.


우선, component-scan은 context Namespace의 하나로, 다음과 같이 Namespace 탭에서 context를 선택하여 추가해야 한다.

Namespace를 등록했으면, xml 설정 파일에 이전에 등록했던 bean 객체를 전부 주석처리 한 다음, 아래와 같이 component-scan을 등록해주기만 하면 xml 파일 작성은 끝이 난다.

 

◎applicationContext.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: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-4.2.xsd">

 	<!--  component-scan -->
 	<context:component-scan base-package="polymorphism"></context:component-scan>
 	
</beans>

이렇게 설정하면 polymorphism 패키지 내부에 모든 소스에 대하여 scan이 들어가며, bean 객체로 등록할 클래스에 다음과 같은 어노테이션만 작성해주면, 굳이 xml 문서 내부에 bean 태그를 이용하여 등록하지 않아도 자동으로 등록이 완료된다.

 

◎SamsungTV

package polymorphism;

import org.springframework.stereotype.Component;

@Component("tv")
public class SamsungTV implements TV{
	
	public SamsungTV() {
		System.out.println("SamsungTV --- 객체 생성");
	}

	@Override
	public void powerOn() {
		System.out.println("SamsungTV --- 전원 켜기");
	}

	@Override
	public void powerOff() {
		System.out.println("SamsungTV --- 전원 끄기");
	}
	
}

의존성 주입:

 

지난 예제들과 같이 SamsungTV에 Speaker라는 맴버 객체를 주입하고 싶다면, 다음의 어노테이션들을 사용하여 따로 xml 파일을 수정하지 않고 주입할 수 있다.


- @Autowired:

주입할 맴버 변수 상단에 작성하면, 해당 객체가 사용되는 지점에서 프로젝트가 자동으로 Autowired어노테이션이 붙은 객체를 찾아 사용한다.

 

◎SamsungTV

package polymorphism;

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

@Component("tv")
public class SamsungTV implements TV{
	
	@Autowired
	private Speaker speaker;
	
	private int price = 0;
	
	public SamsungTV() {
		System.out.println("SamsungTV --- 객체 생성");
	}

	public void setSpeaker(Speaker speaker) {
		System.out.println("setSpeaker");
		this.speaker = speaker;
	}
  
	public void setPrice(int price) {
		System.out.println("setPrice");
		this.price = price;
	}

	@Override
	public void powerOn() {
		System.out.println("SamsungTV --- 전원 켜기");
	}

	@Override
	public void powerOff() {
		System.out.println("SamsungTV --- 전원 끄기");
	}

	@Override
	public void volumeUp() {
		//System.out.println("SamsungTV --- 볼륨 켜기");
		speaker.volumeUp();
		System.out.println(this.price);
	}

	@Override
	public void volumeDown() {
		//System.out.println("SamsungTV --- 볼륨 줄이기");
		speaker.volumeDown();
	}
	
}

 그러나, 이 @Autowired 어노테이션을 사용하기 위해서는 반드시 해당 객체가 bean객체로 선언이 되어 있어야 하기 때문에, 아래 두 방법 중 하나를 선택해서 객체를 등록해야한다.

 

1. ◎applicationContext.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: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-4.2.xsd">
 	
 	<!--  component-scan -->
 	<context:component-scan base-package="polymorphism"></context:component-scan>
 	
 	<bean id = "sony" class = "polymorphism.SonySpeaker"></bean>
 	
</beans>

2. ◎SonySpeaker에 등록

package polymorphism;

import org.springframework.stereotype.Component;

@Component("sony")
public class SonySpeaker implements Speaker {

	public SonySpeaker() {
		System.out.println("==>  SonySpeaker 객체 생성");
	}
	
	/* (non-Javadoc)
	 * @see polymorphism.Speaker#volumeUp()
	 */
	@Override
	public void volumeUp() {
		System.out.println("SonySpeaker --- 볼륨 켜기");
	}

	/* (non-Javadoc)
	 * @see polymorphism.Speaker#volumeDown()
	 */
	@Override
	public void volumeDown() {
		System.out.println("SonySpeaker --- 볼륨 줄이기");
	}

}

- @Qualifier:

Spring container 내에 동일한 타입을 갖는 객체가 여러 개일 경우 사용한다.

 

만약에 위 예제에서 sony 스피커 이외에 Speaker 인터페이스를 구현받는 또 하나의 스피커, apple 스피커가 있다고 가정하면, Spring Container는 Autowired만으로는 둘을 구분하지 못한다. 

이때 Qualifier를 사용하면 각 객체에 이름을 지정해줄 수 있기 때문에, 쉽게 구별할 수 있도록 만들 수 있다.

 

해당 어노테이션은 다음과 같이 사용한다.

 

◎SamsungTV

package polymorphism;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component("tv")
public class SamsungTV implements TV{
	
	@Autowired
	@Qualifier("sony")
	private Speaker speaker;
	
	private int price = 0;
	
	public SamsungTV() {
		System.out.println("SamsungTV --- 객체 생성");
	}

	public void setSpeaker(Speaker speaker) {
		System.out.println("setSpeaker");
		this.speaker = speaker;
	}
  
	public void setPrice(int price) {
		System.out.println("setPrice");
		this.price = price;
	}

	@Override
	public void powerOn() {
		System.out.println("SamsungTV --- 전원 켜기");
	}

	@Override
	public void powerOff() {
		System.out.println("SamsungTV --- 전원 끄기");
	}

	@Override
	public void volumeUp() {
		//System.out.println("SamsungTV --- 볼륨 켜기");
		speaker.volumeUp();
		System.out.println(this.price);
	}

	@Override
	public void volumeDown() {
		//System.out.println("SamsungTV --- 볼륨 줄이기");
		speaker.volumeDown();
	}
	
}

 


- @Resource:

객체의 데이터 타입이 아닌, 객체의 이름을 이용하여 의존성을 주입하는 어노테이션이다.

 

◎SamsungTV

package polymorphism;

import javax.annotation.Resource;
import org.springframework.stereotype.Component;

@Component("tv")
public class SamsungTV implements TV{
	
	@Resource(name="sony")
	private Speaker speaker;
	
	private int price = 0;
	
	public SamsungTV() {
		System.out.println("SamsungTV --- 객체 생성");
	}

	public void setSpeaker(Speaker speaker) {
		System.out.println("setSpeaker");
		this.speaker = speaker;
	}
  
	public void setPrice(int price) {
		System.out.println("setPrice");
		this.price = price;
	}

	@Override
	public void powerOn() {
		System.out.println("SamsungTV --- 전원 켜기");
	}

	@Override
	public void powerOff() {
		System.out.println("SamsungTV --- 전원 끄기");
	}

	@Override
	public void volumeUp() {
		//System.out.println("SamsungTV --- 볼륨 켜기");
		speaker.volumeUp();
		System.out.println(this.price);
	}

	@Override
	public void volumeDown() {
		//System.out.println("SamsungTV --- 볼륨 줄이기");
		speaker.volumeDown();
	}
	
}

 


물론,  <bean> 태그를 이용하여 등록하는 것과 어노테이션을 사용하는 것 둘 다 장,단점이 있기 때문에 이를 혼용하여 사용할 수도 있다.

 

1. 특정 컴포넌트에 주입되는 객체가 자주 변경되어야 할 경우에는 <bean>태그 사용

또한 ~.jar 과 같이 라이브러리 형태로 제공되는 클래스는 반드시 <bean> 태그를 사용한다.

 

2. 특정 컴포넌트에 주입되는 객체가 고정일 경우에는 어노테이션을 이용

 

Comments