컨테이너가 애플리케이션 운용에 필요한 객체를 생성하고 클라이언트는 컨테이너가 생성한 객체를 검색하여 사용하는 방식
객체 사이의 의존관계를 스프링 설정 파일에 등록된 정보를 바탕으로 컨테이너가 자동으로 처리해준다. 따라서 프로그램의 코드를 수정하지 않고 스프링 설정파일 수정만으로 변경사항을 적용할 수 있어 유지보수가 향상된다.
의존성 관계란 객체와 객체의 결합 관계를 말한다.
volumeUp()과 volumeDown() 기능을 가진 SonySpeaker 클래스를 작성한다.
삼성티비가 다음과 같이 SonySpeaker를 가져와 이용하도록 한다.
public class SonySpeaker {
public SonySpeaker() {
System.out.println("===> SonySpeaker 객체 생성");
}
public void volumeUp() {
System.out.println("SonySpeaker --- 소리 올린다.");
}
public void volumeDown() {
System.out.println("SonySpeaker --- 소리 내린다.");
}
}
/****************************************************/
public class SamsungTV implements TV {
private SonySpeaker speaker;
public SamsungTV() {
System.out.println("===> SamsungTV 객체 생성");
}
public void powerOn() {
System.out.println("SamsungTV---전원 켠다.");
}
public void powerOff() {
System.out.println("SamsungTV---전원 끈다.");
}
public void volumeUp() {
speaker = new SonySpeaker();
speaker.volumeUp();
}
public void volumeDown() {
speaker = new SonySpeaker();
speaker.volumeDown();
}
}
TVUser 실행시

문제
1. 소니스피커 객체가 쓸데없이 두 번이나 생성됨
2. 스피커를 변경하고 싶을 때 volumeUp()과 volumeDown()을 모두 수정해야 함
스프링 컨테이너는 XML 설정 파일에 등록된 클래스를 찾아서 객체를 생성할 때 기본적으로 매개변수가 없는 기본(디폴트) 생성자를 호출한다.
컨테이너가 매개변수를 가지는 다른 생성자를 호출하도록 설정해 생성자 인젝션을 처리해보자.
삼성티비 클래스에 소니스피커를 매개변수로 하는 생성자를 만들고, 멤버변수인 speaker로 매개변수로 받은 소니스피커를 갖도록 한다.
생성자 단축키 alt + shift + s
xml 설정
<bean id="tv" class="polymorphism.SamsungTV">
<constructor-arg ref="sony"></constructor-arg>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></bean>
생성자 인자로 전달할 객체의 아이디를 <constructor-arg> 엘리먼트에 ref 속성으로 참조한다.

실행 결과
1. 삼성티비 객체가 생성될 때 기본이 아니라 두 번째 생성자가 사용되었다.
2. 스프링 설정 파일에 소니스피커가 삼성티비 밑에 등록되었는데도 먼저 생성된다.
스프링은 기본적으로 빈 등록 순서대로 객체를 생성하는데, 여기서는 생성자 인젝션으로 의존성 주입될 소니스피커가 먼저 객체 생성되고, 삼성티비가 이를 참조할 수 있게 하고 있다.
초기화할 멤버변수가 여러 개일 때, contructor-arg를 매개변수 개수만큼 추가한다. 인덱스를 지정하면 어떤 값이 몇 번째 매개변수로 매핑되는지 지정할 수 있다.
<bean id="tv" class="polymorphism.SamsungTV">
<constructor-arg index="0" ref="sony"></constructor-arg>
<constructor-arg index="1" value="2700000"></constructor-arg>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></bean>
public class SamsungTV implements TV {
private SonySpeaker speaker;
private int price;
public SamsungTV() {
System.out.println("===> SamsungTV 객체 생성");
}
public SamsungTV(SonySpeaker speaker) {
System.out.println("===> SamsungTV(2) 객체 생성");
this.speaker = speaker;
}
public SamsungTV(SonySpeaker speaker, int price) {
System.out.println("===> SamsungTV(3) 객체 생성");
this.speaker = speaker;
this.price = price;
}
public void powerOn() {
System.out.println("SamsungTV---전원 켠다. (가격 : " + price + ")");
}
public void powerOff() {
System.out.println("SamsungTV---전원 끈다.");
}
public void volumeUp() {
speaker = new SonySpeaker();
speaker.volumeUp();
}
public void volumeDown() {
speaker = new SonySpeaker();
speaker.volumeDown();
}
}
Speaker 인터페이스를 만든다.
삼성티비에 Setters를 만든다.
스프링 설정 xml에 constructor-arg대신 property를 이용해야 한다.
name값이 호출하고자 하는 메소드 이름이다. 즉 name값이 speaker이면 setSpeaker를 호출한다.
<bean id="tv" class="polymorphism.SamsungTV">
<property name="speaker" ref="apple"></property>
<property name="price" value="2700000"></property>
</bean>
<bean id="sony" class="polymorphism.SonySpeaker"></bean>
<bean id="apple" class="polymorphism.AppleSpeaker"></bean>
Namespaces 탭에서 추가한다.
xmlns:p="http://www.springframework.org/schema/p"
p:변수명-ref="참조할 객체의 이름이나 아이디"
p:변수명="설정할 값"