Auto-wiring (의존 관계 자동 설정)
개념
- Dependency Injection을 명시적으로 설정하지 않아도 container가 bean의 타입이나 이름을 이용하여 DI를 자동으로 수행하는 기능
- XML 설정 방법
- <bean> 엘리먼트에 autowire 속성을 이용하여 자동 설정 방식 지정
- 모든 bean 객체들에 대해 특정 방식을 적용하려면 <beans> 엘리먼트에 default-autowire 속성 이용
autowire 값 | 의미 |
no (default) | auto-wiring을 수행하지 않음 |
byName | property와 같은 이름 또는 id 값을 갖는 bean을 찾아 주입 (setter-based injection) |
byType | property와 같은 타입을 갖는 bean을 찾아 주입 (setter-based injection) |
constructor | 생성자 호출시 인자(argument)와 같은 타입을 갖는 bean을 찾아 전달 (constructor-based injection) |
예
public class Instrumentalist implements Performer {
private String song; // property (값)
private Instrument instrument; // property (객체 참조)
private Company affiliation; // property (객체 참조)
public Instrumentalist() { } // default constructor
public Instrumentalist(Instrument instrument) { // constructor
this.instrument = instrument;
}
public Instrumentalist(Instrument instrument, String song) { // constructor
this.instrument = instrument; this.song = song;
}
public void setSong(String song) { this.song = song; } // setter method
public void setInstrument(Instrument instrument) { // setter method
this.instrument = instrument;
}
…
}
1. byName (setter-based injection)
<bean id="instrument" class="com.example.springidol.Saxophone" />
<bean id="kenny" class="com.example.springidol.Instrumentalist"
autowire="byName">
<property name="song" value="Jingle Bells" />
</bean>
↓
<bean id="kenny" class="com.example.springidol.Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="instrument" />
</bean>
- Setter method를 이용하여 property 이름과 같은 id를 갖는 bean을 선택하여 주입
- 단, 그 bean의 타입이 property의 타입과 같거나 할당가능한 타입이어야 함
2. byType (setter-based injection)
<bean id="saxophone" class="com.example.springidol.Saxophone" />
<bean id="kenny" class="com.example.springidol.Instrumentalist"
autowire="byType">
<property name="song" value="Jingle Bells" />
</bean>
↓
<bean id="kenny" class="com.example.springidol.Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="saxophone" />
</bean>
- saxophone bean은 Instrument를 구현한 클래스의 객체이므로 Instrument 타입 property에 주입 가능
- Instrument 타입의 객체가 하나만 존재할 경우 그것을 setter method를 통해 주입
3. constructor (constructor-based injection)
<bean id="saxophone" class="com.example.springidol.Saxophone" />
<bean id="kenny" class="com.example.springidol.Instrumentalist"
autowire="constructor" />
↓
<bean id="kenny" class="com.example.springidol.Instrumentalist">
<constructor-arg ref="saxophone" />
</bean>
- Instrumentalist 클래스에 Instrument 타입의 인자를 갖는 생성자가 존재하고, saxophone bean이 유일한 Instrument 타입 객체일 때 saxophone bean을 생성자를 통해 주입
Auto-wiring과 명시적 설정의 혼합
- 자동 설정 이용시 일부 property에 대해 명시적인 DI 설정 가능
- <property>나 <constructor-arg> 이용
- 명시적인 설정은 auto-wiring보다 우선적으로 적용
<bean id="saxophone" class="com.example.springidol.Saxophone" />
<bean id="kenny" class="com.example.springidol.Instrumentalist" autowire="byType">
<property name="affiliation" ref="sonymusic"/> <!-- 명시적인 DI 설정 -->
</bean>
- affiliation property: 명시적으로 지정된 bean(sonymusic)이 주입됨
- instrument property: DI 설정이 생략되었으므로 byType 방식에 의해 auto-wiring 실행 → saxophone bean 주입
주의
- byName, byType 방식
- 주입 가능한 bean이 없을 경우 dependency injection 수행 안 함 → 에러는 발생하지 않지만 의존 객체가 주입되지 않은 상태이므로 나중에 프로그램 실행시 문제가 될 수 있음
- byType, constructor 방식
- 주입 가능한 bean이 여러 개 있을 경우 exception 발생 → NoUniqueBeanDefinitionException
- constructor 방식
- 자동 주입에 사용 가능한 생성자가 여러 개일 경우 exception 발생
부모 Bean을 통한 설정 재사용
개념
- Bean들 사이에 중복되는 설정이 많을 경우 추상 bean을 정의하고 그 설정을 재사용(상속)
- <bean>에서 abstract, parent 속성 사용
- abstract="true" : 추상 bean을 정의 (객체 생성 불가)
- parent="bean ID" : 자식 bean에서 부모(추상) bean의 id 지정
- 자식 bean은 부모 bean의 class와 property 설정을 상속받음
- 상속받은 class나 property 설정을 재정의(override)하거나 새로운 property 설정 추가 가능
예 1
<bean id="kenny" class="com.example.springidol.Instrumentalist"> → id 외에는 모두 동일
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="saxophone" />
</bean>
<bean id="david" class="com.example.springidol.Instrumentalist"> → id 외에는 모두 동일
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="saxophone" />
</bean>
↓
<bean id="saxophonist" class="com.example.springidol.Instrumentalist"
abstract="true"> 추상 bean
<property name="instrument" ref="saxophone" />
<property name="song" value="Jingle Bells" />
</bean>
<bean id="kenny" parent="saxophonist" />
<bean id="david" parent ="saxophonist" />
<bean id="frank" parent ="saxophonist" >
<property name="song" value="May had a little ramb" />
</bean>
- 6~8행: song과 instrument에 대한 DI 설정을 상속받음
예 2
<bean id="taylor" class="com.example.springidol.Vocalist">
<property name="song" value="Somewhere Over the Rainbow" /> → 동일
</bean>
<bean id="stevie" class="com.example.springidol.Instrumentalist">
<property name="song" value="Somewhere Over the Rainbow" /> → 동일
<property name="instrument" ref="guitar" />
</bean>
↓
<bean id="basePerformer" abstract="true">
<property name="song" value="Somewhere Over the Rainbow" />
</bean>
<bean id="taylor" class="com.example.springidol.Vocalist"
parent="basePerformer">
<bean id="stevie" class="com.example.springidol.Instrumentalist"
parent="basePerformer">
<property name="instrument" ref="guitar" />
</bean>
- 1행: 부모 bean의 class 설정 생략 가능
- 4, 6행: class 설정
- 8행: 새로운 DI 설정 추가
'프로그래밍 > Spring' 카테고리의 다른 글
[Spring] DI - XML 기반 설정 (0) | 2022.04.24 |
---|---|
[Spring] Spring MVC(2) (0) | 2022.04.22 |
[Spring] Spring MVC(1) (0) | 2022.04.17 |
[Spring] Spring DI (0) | 2022.04.01 |