SpringFramework Annotation 을 이용한 의존성 주입(DI)
저번 게시글에서는 Construct Injection , Set Injection 으로
의존성을 주입시키는 방법을 알아봤다.
이제 더 편하고 새로운 방식인 Annotation 을 이용해보자.
Annotation 이란 자바 소스코드 안에 추가하여 사용할 수 있는
메타데이터의 일종인데, 자세한 내용은
https://elfinlas.github.io/2017/12/14/java-annotation/ 를 참고하자.
저번 예제를 이용하여 Annotation 을 사용해보자.
먼저 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: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 https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.yopy.annotation"/>
</beans>
<context:component-scan base-package="com.yopy.annotation"/>
라인이 xml 에 추가되었는데 , base-package 는 com.yopy.annotation 패키지로
시작하는 모든 패키지를 스캔하여 BeanPostProcessor , Autowired 등
기능을 수행할 수 있게 설정한 것이다.
package com.yopy.annotation;
import org.springframework.stereotype.Component;
@Component("tv")
//<bean id ="tv" class="com.yopy.annotation.LgTv"></bean> 와 같은 의미이다.
public class LgTv implements TV {
public LgTv() {
System.out.println("LG TV Constructor Created");
}
public void powerOn() {
System.out.println("LG TV PowerON");
}
public void powerOff() {
System.out.println("LG TV PowerOff");
}
public void volumeUp() {
System.out.println("LG TV VolumeUp");
}
public void volumeDown() {
System.out.println("LG TV VolumeDown");
}
}
전 게시글에선 xml 에 가서 직접 빈을 설정하고 클래스를 매핑하였지만 이제는
그 과정이 @Component 한줄로 끝난것이다.
package com.yopy.annotation;
public interface TV {
void powerOn();
void powerOff();
void volumeUp();
void volumeDown();
}
TV 클래스는 전 게시글과 같다.
package com.yopy.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class TVUser {
public static void main(String[] args) {
ApplicationContext factory = new GenericXmlApplicationContext("spring/rootContext.xml");
TV tv = (TV)factory.getBean("tv");
tv.powerOn();
tv.volumeUp();
tv.volumeDown();
tv.powerOff();
}
}
실행하여 결과를 확인해보자.
그리고 이제 스피커를 소니 스피커로 바꿔보자.
package com.yopy.annotation;
public interface Speaker {
void volumeDown();
void volumeUp();
}
스피커 공통 속성이 담긴 인터페이스를 생성하자.
package com.yopy.annotation;
import org.springframework.stereotype.Component;
@Component("sony")
public class SonySpeaker implements Speaker {
public SonySpeaker() {
System.out.println("SonySpeaker Constructor Created");
}
public void volumeDown() {
System.out.println("SonySpeaker Volume Down");
}
public void volumeUp() {
System.out.println("SonySpeaker Volume Up");
}
}
여기서도 역시 sony 라는 이름으로 컴포넌트 어노테이션이 사용되었다.
빈에 자동으로 등록된다.
package com.yopy.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("tv")
//<bean id ="tv" class="com.yopy.annotation.LgTv"></bean> 와 같은 의미이다.
public class LgTv implements TV {
@Autowired
private Speaker speaker;
public LgTv(Speaker speaker) {
System.out.println("LG TV 객체 생성");
this.speaker = speaker;
}
public LgTv() {
System.out.println("LG TV Constructor Created");
}
public void powerOn() {
System.out.println("LG TV PowerON");
}
public void powerOff() {
System.out.println("LG TV PowerOff");
}
public void volumeUp() {
speaker.volumeUp();
}
public void volumeDown() {
speaker.volumeDown();
}
}
여기서 멤버변수 위에 @Autowired 가 사용되었는데,
이것은 자동으로 Speaker 타입의 객체를 연결시켜준다.
TVUser 클래스는 수정하지 않아도 된다.
내용을 실행해보면 스피커가 소니스피커로 바뀐 모습을 볼 수 있다.
그런데 이번에는 소니 스피커에서 애플 스피커로 바꾸고싶다.
기존에 소니 스피커를 버릴순 없으니 유지시키고 어노테이션을 이용하여
애플 스피커로 교체해보자.
package com.yopy.annotation;
import org.springframework.stereotype.Component;
@Component("apple")
public class AppleSpeaker implements Speaker {
public AppleSpeaker() {
System.out.println("Apple Speaker Constructor Created");
}
public void volumeDown() {
System.out.println("Apple Speaker Volume Down");
}
public void volumeUp() {
System.out.println("Apple Speaker Volume Up");
}
}
AppleSpeaker 클래스를 만들고 컴포넌트를 생성했다.
그런데 사실 @Autowired 는 사용자가 소니스피커를
원하는지 애플 스피커를 원하는지 알 수 없다.
그래서 우리는 @Qualifier 을 사용하여 티비에서 애플스피커를
쓰라고 알려줄 것이다.
package com.yopy.annotation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("tv")
//<bean id ="tv" class="com.yopy.annotation.LgTv"></bean> 와 같은 의미이다.
public class LgTv implements TV {
@Autowired
@Qualifier("apple")
private Speaker speaker;
public LgTv(Speaker speaker) {
System.out.println("LG TV 객체 생성");
this.speaker = speaker;
}
public LgTv() {
System.out.println("LG TV Constructor Created");
}
public void powerOn() {
System.out.println("LG TV PowerON");
}
public void powerOff() {
System.out.println("LG TV PowerOff");
}
public void volumeUp() {
speaker.volumeUp();
}
public void volumeDown() {
speaker.volumeDown();
}
}
@Qualifier 에 방금 만든 애플 컴포넌트 이름이 들어갔다.
이렇게 되면 정상적으로 애플 스피커로 인식하여 작동하게 된다.