The Debugging Chronicles : "코드의 미학"

[Spring] 의존성(Dependency) - 생성자 주입 본문

Spring

[Spring] 의존성(Dependency) - 생성자 주입

sweetseonah1004 2024. 10. 2. 10:19

객체생성(new)을 컨테이너로 대신한다 === IoC의 핵심 === Spring 사용하는 이유


"의존성(dependency)"이란?

: 어떤 코드를 수행할 때에 필요한 다른 부분의 코드 내용이 있는가?

 

"주입(injection)"이란?

: 필요한 다른 부분의 코드 내용을 추가하는 것

 

"의존성 주입" == DI


Watch를 통해서 IPhone 전원을 켜보자.

 

근데 위에 코드는 메서드가 실행될 때 마다 new가 된다.

즉, 아이폰은 워치에 대해 의존성을 갖는다.

 

그래서 다음과 같이 코드를 바꿀 수 있다.

해당 객체를 멤버변수로 두면 관리가 용이하다.

지금은 객체가 없는 상황이다.

메모리를 주어야한다.

그래서 watch에 의존성 주입을 해야한다.

 

그럼 의존성 주입하는 방법을 알아보자.


의존성 주입하는데는 두가지 방법이 있다.

 

1. 생성자 주입 

- handler mapper

2. Setter 주입

- DTO

 

1. 생성자 주입

기본 생성자의 멤버변수 메모리를 추가하는 방법은 무조건 new 연산자가 반드시 들어간다

그래서 외부에서, 즉 다른 생성자를 만들어서

메모리를 받아 멤버변수를 셋팅하는 방법을 사용한다.

 

 

로그를 살펴볼 필요가 있다. 왜 순서가 이렇게 나왔을까?

 

 

 

원시 타입 넣는 방법

 

 

ref 은 객체를 주입하는 것

value는 값을 주입하는 것이다.

 

 

 

 


 

다시 한번 해보자

 

 

의존성 주입 때문에 코드 순서 대로 로그가 나오는 것이 아니라 

8번 라인이 먼저 실행되고 그 다음에 7번 라인이 실행되고

12번 라인이 먼저 실행되고 그 다음에 11번 라인이 실행된다.

12번 라인이 실행 될 때 갤럭시워치만 되고 아이폰워치는 한번 더 실행되지 않는 이유는 싱글톤 때문이다.

 


Watch.java

package test;

public interface Watch {
	void powerOn();
	void powerOff();
}

 

 

Phone.java

package test;

public interface Phone {
	public abstract void powerOn(); // 추상메서드
	void powerOff();
}

 

 

IPhone.java

package test;

public class IPhone implements Phone {
	private Watch watch;
	private int num;
	
	public IPhone() {
		System.out.println("아이폰 객체 생성 01");
	}
	public IPhone(Watch watch) {
		this.watch=watch;
		System.out.println("아이폰 객체 생성 02");
	}
	public IPhone(Watch watch,int num) {
		this.watch=watch;
		this.num=num;
		System.out.println("아이폰 객체 생성 03");
	}

	@Override
	public void powerOn() {
		this.watch.powerOn();
		System.out.println("num = "+this.num);
	}
	@Override
	public void powerOff() {
		this.watch.powerOff();
	}	
}

 

 

GalaxyWatch.java

package test;

public class GalaxyWatch implements Watch {

	public GalaxyWatch() {
		System.out.println("갤럭시워치 생성자 호출");
	}
	
	@Override
	public void powerOn() {
		System.out.println("갤럭시워치 ON");
	}
	@Override
	public void powerOff() {
		System.out.println("갤럭시워치 OFF");	
	}

}

 

 

GalaxyPhone.java

package test;

public class GalaxyPhone implements Phone {
	private Watch watch;
	
	public GalaxyPhone() {
		System.out.println("갤럭시 객체 생성 01");
	}
	public GalaxyPhone(Watch watch) {
		this.watch=watch;
		System.out.println("갤럭시 객체 생성 02");
	}

	@Override
	public void powerOn() {
		this.watch.powerOn();
	}
	@Override
	public void powerOff() {
		this.watch.powerOff();
	}	
}

 

 

Client.java

package test;

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

public class Client {
	public static void main(String[] args) {
		
		AbstractApplicationContext factory = new GenericXmlApplicationContext("applicationContext.xml");
		// 컨테이너를 구동시키는 코드
		
		Phone phone = (Phone)factory.getBean("apple");
		// Bean == 자바객체 == 객체 == POJO
		// 객체를 요청하다.
		// == look up
		
		phone.powerOn();
		phone.powerOff();
		
		factory.close();
		
	}
}

 

 

AppleWatch.java

package test;

public class AppleWatch implements Watch {

	public AppleWatch() {
		System.out.println("애플워치 생성자 호출");
	}
	
	@Override
	public void powerOn() {
		System.out.println("애플워치로 ON");
	}
	@Override
	public void powerOff() {
		System.out.println("애플워치로 OFF");
	}

}

 

 

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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans.xsd">
	
	<bean class="test.IPhone" id="apple">
		<constructor-arg ref="aw" />
		<constructor-arg value="1234" />
	</bean>
	<bean class="test.GalaxyPhone" id="samsung">
		<constructor-arg ref="gw" />
	</bean>
	
	<bean class="test.AppleWatch" id="aw" />
	<bean class="test.GalaxyWatch" id="gw" />
	
</beans>