티스토리 뷰

spring

day1 class05 어노테이션 기반 설정

일상다반ㅅㅏ 2018. 12. 22. 18:21

1. context 네임스페이스 추가

p 네임스페이스 추가와 마찬가지로 [namespaces] > context 항목 체크하면 다음과 같이 소스가 추가된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 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">
 
    <context:component-scan base-package="polymorphism"></context:component-scan>
    <bean class="polymorphism.SonySpeaker"></bean>
    <!-- <bean id="tv" class="polymorphism.LgTV"></bean> -->
</beans>
cs



2. 컴포넌트 스캔(component-scan) 설정

- <context:component-scan> 엘리먼트를 정의하면 애플리케이션에서 사용할 객체들을 <bean>등록을 하지 않고 자동으로 생성할 수 있다.

-  base-package속성값은 해당 경로의 패키지로 시작하는 모든 클래스들이 스캔 대상이 된다.



3. @Component

- 해당 클래스에 기본 생성자가 있어야만 한다.

- 3.1과 3.2의 방법 중 하나를 사용하면 constructor injection이나 setter injection을 이용하지 않아도 된다.

- id나 name 속성 미지정 시 컨테이너가 자동으로 해당 클래스의 첫 글자를 소문자로 변경하여 설정해준다.


3.1 XML 설정

1
<bean id="tv" class="polymorphism.LgTV"></bean>
cs

3.2 Annotation 설정

1
2
@Component("tv")
public class LgTV implements TV {
cs



4. 의존성 주입 어노테이션

4.1 @Autowired

- 주로 변수 위에 설정하여 해당 타입의 객체를 찾아서 자동으로 할당한다.

- 해당 어노테이션을 확인하는 순간 해당 변수의 타입을 체크하고 객체가 메모리에 존재하는지 학인한 후, 그 객체를 변수에 주입한다.

- 객체가 메모리에 없다면 NoSuchBeanDefinitionException을 발생시킨다.

- 4.1.1이나 4.1.2 둘 중 하나의 방법을 선택하여 사용하면 된다.

- SonySpeaker와 AppleSpeaker로 Speaker의 객체가 두개 이상이면 NoUniqueBeanDefinitionException~~~but found 2: apple, sony를 발생시킨다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package polymorphism;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component("tv")
public class LgTV implements TV {
    
    @Autowired
    private Speaker speaker;
    
    public LgTV() {
        System.out.println("===> LgTV 객체 생성");
    }
    // 생략 //
    public void volumeUp() {
        speaker.volumeUp();
    }
    public void volumeDown() {
        speaker.volumeDown();
    }
}
cs

4.1.1 XML 설정

<bean class="polymorphism.SonySpeaker"></bean>

cs

4.1.2 Annotation 설정

1
2
3
4
import org.springframework.stereotype.Component;
 
@Component("sony")
public class SonySpeaker implements Speaker {
cs

4.2 @Qualifier

- 특정 객체의 이름을 이용하여 의존성 주입할 때 사용한다.

- 4.1의 문제 해결을 위해 사용한다.

- 해당 어노테이션으로 Speaker 객체를 지정하여 문제를 해결 할 수 있다.

1
2
3
4
5
6
7
8
9
10
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
 
@Component("tv")
public class LgTV implements TV {
    
    @Autowired
    @Qualifier("apple")
    private Speaker speaker;
cs

4.3 @Resource

- @Autowired와 @Qualifier의 기능을 결합한 어노테이션이다.

1
2
3
4
5
6
7
8
9
import javax.annotation.Resource;
 
import org.springframework.stereotype.Component;
 
@Component("tv")
public class LgTV implements TV {
    
    @Resource(name="apple")
    private Speaker speaker;
cs



5. 어노테이션과 XML 설정 병행하여 사용하기

- XML방식은 자바 소스를 수정하지 않고 XML파일의 설정만 변경하여 Speaker을 교체할 수 있다. 유지 보수가 편하지만 XML 설정에 대한 부담이 있고 자바 소스에 의존관계와 관련된 어떤 메타데이터도 없으므로 XML 설정을 해석해야만 무슨 객체가 의존성 주입되는지를 확인할 수 있다.

- 어노테이션 기반 설정은 XML 설정에 부담이 없고 의존관계에 대한 정보가 자바 소스에 드렁있어서 사용하기는 편하지만 의존성 주입할 객체의 이름이 자바 소스에 명시되어야 하므로 소스를 수정해야 한다.

- 위의 두 방법의 장점을 조합하여 사용한다.

- 클라이언트가 요청할 LgTV는 @Component 어노테이션으로 처리하고, 의존성 주입은 @Autowired로 처리한다. 다만, 변경될 Speaker만 스프링 설정 파일에 <bean> 등록함으로써 자바 코드 수정 없이 XML 수정만으로 Speaker를 교체할 수 있다.

- 변경되지 않는 객체는 어노테이션으로 설정하여 사용하고, 변결될 가능성이 있는 객체는 XML 설정으로 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package polymorphism;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@Component("tv")
public class LgTV implements TV {
    
    @Autowired
    private Speaker speaker;
    
    public LgTV() {
        System.out.println("===> LgTV 객체 생성");
    }
    public void powerOn() {
        System.out.println("LgTV---powerOn");
    }
    public void powerOff() {
        System.out.println("LgTV---powerOff");
    }
    public void volumeUp() {
        speaker.volumeUp();
    }
    public void volumeDown() {
        speaker.volumeDown();
    }
}
cs


- 객체가 자동으로 생성되는것을 차단한다.

1
2
3
4
5
//@Component("sony") ==> 제거
public class SonySpeaker implements Speaker {
 
//@Component("apple") ==> 제거
public class AppleSpeaker implements Speaker {
cs


1
2
3
4
5
6
7
8
9
10
11
12
<?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">
 
    <context:component-scan base-package="polymorphism"></context:component-scan>
    <bean class="polymorphism.SonySpeaker"></bean>
    <!-- <bean class="polymorphism.AppleSpeaker"></bean> -->
</beans>
cs