Spring Boot&Framework

SpringFramework Annotation 을 이용한 의존성 주입(DI)

요피짱 2020. 1. 21. 23:03

저번 게시글에서는 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 에 방금 만든 애플 컴포넌트 이름이 들어갔다.

이렇게 되면 정상적으로 애플 스피커로 인식하여 작동하게 된다.