스프링 DI(의존주입)-3

1.의존 자동 주입-1

스프링은 프레임워크 자체에서 자동으로 의존 객체를 찾아 주입해주는 기능을 지원한다.
설정 방법 또한 간단하다.

  1. 설정 XML 내에 <context:annotation-config/> 추가
  2. 의존 주입 대상에 @Autowired 어노테이션 작성

@Autowired 어노테이션을 이용한 의존 자동 주입에도 여러가지 방법이 존재한다.

  • 생성자 자동 주입
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public calss MemberRegisterService {
    private MemberDao memberDao;

    @Autowired
    public MemberRegisterService(MemberDao memberDao) { // 의존 주입
    this.memberDao = memberDao;
    }
    ...
    }

위와 같이 생성자에 @Autowired 어노테이션을 추가하여 의존 객체를 자동 주입할 수 있다.

  • 필드 자동 주입
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public calss MemberRegisterService {
    @Autowired
    private MemberDao memberDao; // 의존 주입

    public MemberRegisterService(MemberDao memberDao) {
    this.memberDao = memberDao;
    }
    ...
    }

이와 같이 필드에 @Autowired 어노테이션을 추가하는 방법이 있다.

  • 설정 메소드 자동 주입
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public calss MemberPrinter {
    private MemberPrinter printer;

    @Autowired
    public void setPrinter(MemberPrinter printer) { // 의존 주입
    this.printer = printer;
    }
    ...
    }

마지막으로 설정 메소드에 어노테이션을 추가하는 방법도 있다.

이와 같은 방법으로 의존 객체를 자동 주입할 경우 앞서 사용했던 constructor-arg나 property 태그를 사용하지 않아도 된다.

1
2
3
4
5
<context:annotation-config/> // Autowired 처리

<bean id="memberRegSvc" class="kr.co.jhdev.MemberRegisterService"></bean> // Bean 등록

<bean id="memberPrinter" class="kr.co.jhdev.MemberPrinter"></bean> // Bean 등록

2. Autowired의 기본적인 특성

그렇다면 스프링은 어떻게 객체를 자동으로 주입할 수 있을까?

우선 스프링은 같은 유형에 속하는 빈 객체를 검색해 주입 대상을 선택한다.

예를 들어 B라는 클래스는 A를 상속 받아 만들어졌다고 가정하자
B 클래스가 Bean에 등록되있으면서 A 클래스를 생성/설정하는 생성자 혹은 필드, 설정 메소드에 Autowired 어노테이션을 추가한다면
B 클래스는 A 클래스를 상속 받아 생성된 같은 유형이므로 B 클래스를 자동 할당해준다.
자동 주입에서의 타입 매칭

만약 동일한 유형의 빈 객체 두 개가 등록 되어 있다면 어떻게 될까?
이런 경우 어떤 클래스를 할지 판단할 수 없어 ‘NoUniqueBeanDefinitionException’이 발생한다.

이러한 문제를 해결하기 위해 @Qualifier 어노테이션을 사용할 수 있다.

3. Qualifier를 이용한 의존 주입 객체 선택

Qualifier 어노테이션을 이용하면 동일한 유형의 클래스 다수가 Bean에 등록되어 있더라도 주입할 의존 객체를 개별적으로 선택할 수 있다.

  1. 설정 XML 내 등록 된 Bean에 한정자 태그(qualifier)와 값을 설정한다.
  2. Autowired 적용 대상에 Qualifier을 추가하고 한정자 값을 입력한다.
1
2
3
4
5
6
7
<context:annotation-config/> // Autowired 처리

<bean id="memberPrinter" class="kr.co.jhdev.MemberPrinter">
<qualifier value="sysout" /> // 한정자 값 설정
</bean> // Bean 등록

<bean id="memberPrinter2" class="kr.co.jhdev.MemberPrinter"></bean> // Bean 등록

위와 같이 동일한 유형의 객체가 Bean에 등록한 후 한정자 값을 설정한다.

1
2
3
4
5
6
7
8
9
10
public calss MemberPrinter {
private MemberPrinter printer;

@Autowired
@Qualifier("sysout")
public void setPrinter(MemberPrinter printer) { // 의존 주입
this.printer = printer;
}
...
}

Autowired 어노테이션과 함께 Qualifier 어노테이션을 기입하면 객체를 선택 주입할 수 있다.

  • 한정자 값을 잘못 기입하면 Exception을 발생시키니 유의해야한다.

4. Autowired 필수 여부 지정

만약 Autowired 어노테이션을 추가했지만 Bean이 등록되어 있지 않다면 어떻게 될까?
당연하게도 스프링 컨테이너 생성 시, Exception이 발생한다.

이를 막기 위해 Autowired 어노테이션의 required(필수) 여부를 변경할 수 있다.

1
2
3
4
5
public calss MemberPrinter {
@Autowired(required=false)
private MemberPrinter printer; // 의존 주입했지만 Bean이 등록되지 않았다.
...
}

위와 같이 필수 여부를 false 처리할 경우 컨테이너 생성 시, Exception이 발생하지 않는다.
하지만 이는 필수 여부이지 의존 객체를 주입하지 않는다는 의미는 아니다.
required=false로 처리했더라도 같은 유형의 객체가 등록되어 있다면 객체는 자동 주입된다.
단순히 객체가 존재하지 않아도 Exception을 발생시키지 않는 설정이라고 생각하면 편하다.

5. Autowired의 동작 순서

Autowired의 기본적인 특성에 대해 알아봤으며 마지막으로 동작 순서로 정리한다.
스프링에서 Autowired 어노테이션 추가 시, 동작하는 순서는 아래와 같다.

  1. 동일 타입의 객체를 검색하고 1개일 경우, 해당 객체를 사용한다.
    Qualifier가 입력된 경우 Qualifier 설정 값이 동일한 빈을 찾는다.
  1. 타입이 같은 빈이 2개 이상일 경우, Qualifier 설정 값이 동일한 빈을 찾는다.
  1. 타입이 같은 빈이 2개 이상이며 Qualifier 설정 값이 없는 경우,
    이름이 같은 빈 객체를 찾는다.
  1. 모두 해당하지 않으면 Exception이 발생한다.
Share