Spring/실습 정리

Spring 2강 - 생성자 주입과 다형성 객체 활용

코딩하는냥이 2025. 6. 16. 15:21
반응형

이번 시간에는 생성자(Constructor)를 이용한 의존성 주입(DI) 방법과, 하나의 인터페이스를 다양한 구현체로 바꿔가며 사용하는 다형성 기반 DI를 실습합니다.


📦 TV.java

package example;

public interface TV {
	public void powerOn();
	public void powerOff();
	public void volumeUp();
	public void volumeDown();
}

📦 Speaker.java

package example;

public interface Speaker {
	public void volumeUp();
	public void volumeDown();
}

📦 AppleSpeaker.java

package example;

public class AppleSpeaker implements Speaker {
	public AppleSpeaker(){
		System.out.println(getClass().getSimpleName() + " 객체 생성");
	}
	public void volumeUp() {
		System.out.println(getClass().getSimpleName() +" 볼륨 업");
	}
	public void volumeDown() {
		System.out.println(getClass().getSimpleName() +" 볼륨 다운");
	}
}

📦 BossSpeaker.java

package example;

public class BossSpeaker implements Speaker {
	public BossSpeaker(){
		System.out.println(getClass().getSimpleName() + " 객체 생성");
	}
	public void volumeUp() {
		System.out.println(getClass().getSimpleName() +" 볼륨 업");
	}
	public void volumeDown() {
		System.out.println(getClass().getSimpleName() +" 볼륨 다운");
	}
}

📦 SamsungTv.java

package example;

public class SamsungTv implements TV {
	private Speaker speaker;
	private int price;

	public SamsungTv() {
		System.out.println(getClass().getSimpleName() + " 객체 생성");
	}

	public SamsungTv(Speaker speaker) {
		System.out.println(getClass().getSimpleName() + " 객체 생성 2");
		this.speaker = speaker;
	}

	public SamsungTv(Speaker speaker, int price) {
		System.out.println(getClass().getSimpleName() + " 객체 생성 3");
		this.speaker = speaker;
		this.price = price;
	}

	public void powerOn() {
		System.out.println(getClass().getSimpleName() + "전원을 켭니다 : " + price);
	}

	public void powerOff() {
		System.out.println(getClass().getSimpleName() + "전원을 끕니다.");
	}

	public void volumeUp() {
		speaker.volumeUp();
	}

	public void volumeDown() {
		speaker.volumeDown();
	}
}

📦 LgTv.java

package example;

public class LgTv implements TV {
	private Speaker speaker;
	private int price;

	public LgTv() {
		System.out.println(getClass().getSimpleName() + " 객체 생성");
	}

	public LgTv(Speaker speaker) {
		System.out.println(getClass().getSimpleName() + " 객체 생성 2");
		this.speaker = speaker;
	}

	public LgTv(Speaker speaker, int price) {
		System.out.println(getClass().getSimpleName() + " 객체 생성 3");
		this.speaker = speaker;
		this.price = price;
	}

	public void powerOn() {
		System.out.println(getClass().getSimpleName() + "전원을 켭니다 : " + price);
	}

	public void powerOff() {
		System.out.println(getClass().getSimpleName() + "전원을 끕니다.");
	}

	public void volumeUp() {
		speaker.volumeUp();
	}

	public void volumeDown() {
		speaker.volumeDown();
	}
}

📌 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
	       http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<bean id="stv" class="example.SamsungTv">
		<constructor-arg ref="apple"/>
		<constructor-arg value="2700000"/>
	</bean>

	<bean id="ltv" class="example.LgTv">
		<constructor-arg ref="boss"/>
		<constructor-arg value="2700000"/>
	</bean>

	<bean id="apple" class="example.AppleSpeaker"/>
	<bean id="boss" class="example.BossSpeaker"/>
</beans>

📌 TvUser.java

package example;

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

public class TvUser {
	public static void main(String[] args) {
		AbstractApplicationContext factory =
			new GenericXmlApplicationContext("applicationContext.xml");

		TV tv = (TV) factory.getBean("stv");
		tv.powerOn();
		tv.volumeUp();
		tv.volumeDown();
		tv.powerOff();

		tv = (TV) factory.getBean("ltv");
		tv.powerOn();
		tv.volumeUp();
		tv.volumeDown();
		tv.powerOff();
	}
}

💻 실행 결과 (예시)

AppleSpeaker 객체 생성
BossSpeaker 객체 생성
SamsungTv 객체 생성 3
LgTv 객체 생성 3
SamsungTv전원을 켭니다 : 2700000
AppleSpeaker 볼륨 업
AppleSpeaker 볼륨 다운
SamsungTv전원을 끕니다.
LgTv전원을 켭니다 : 2700000
BossSpeaker 볼륨 업
BossSpeaker 볼륨 다운
LgTv전원을 끕니다.

💬 코드 설명

  • Speaker 인터페이스를 통해 볼륨 조절 기능을 추상화하고, AppleSpeaker와 BossSpeaker 두 구현 클래스를 구성했습니다.
  • SamsungTv와 LgTv는 Speaker를 생성자가 주입받아 사용하는 구조입니다.
  • applicationContext.xml에서는 constructor-arg를 통해 Speaker 객체와 가격을 주입합니다.
  • TvUser에서는 설정에 따라 TV 객체를 받아서 실행할 뿐, 직접 new하지 않습니다.

💡 포인트 정리

  • 생성자 주입(Constructor Injection) 방식은 객체 생성 시 의존 객체를 반드시 전달해야 할 때 적합합니다.
  • 인터페이스 기반 설계를 통해 다형성 활용이 가능해지고, 설정 파일만 바꾸면 기능 변경이 쉬워집니다.
  • constructor-arg ref="beanId"를 통해 외부 Bean을 연결, value로 단순 값을 전달합니다.

📌정리하자면, 이번 강의에서는 생성자 주입 방식으로 의존 객체를 전달받는 방법다형성을 활용하여 다양한 구현 객체를 주입하는 구조를 실습했습니다. 스프링에서는 이런 설정을 통해 코드 변경 없이 다양한 객체를 조합해 사용할 수 있어 유연한 개발이 가능해집니다.