* 의존성 주입이란?

 

의존성 주입이란 클래스와 클래스 사이의 연관관계를 개발자가 아닌 스프링 컨테이넝에서 규정하는 것을 뜻합니다.

클래스 내에서 직접 객체를 생성하여 사용하는 경우,  복잡할수록 유지보수가 복잡해지는 특징이 있습니다. 이러한 경우를 강한 결합이라고 하며, 해당 클래스 외에 다른 클래스의 변경사항이 연속적으로 다른 부분에 영향을 미친다면, 이러한 강한 결합은 좋은 방법이 아닙니다.

 

예를들어, 자동차의 에어컨이 고장나면 에어컨만 수리하면 되는데, 에어컨 기능이 자동차 엔진과 관련있게 설계되었다면 에어컨의 작은 문제라도 생기면 엔진까지 손봐야 하는 상황이 됩니다.

그러므로, 같은 기능끼리는 강하게 결합하고, 관련이 크게 없는 기능에게는 영향을 주지 않게 설계된 자동차가 좋은 자동차라고 할 수 있습니다.

마찬가지로 프로그램을 짜면서도 관련이 있는 기능들은 강하게 결합하고, 관련이 없는 기능들은 약하게 결합해야 좋은 프로젝트입니다.

위의 예시를 바탕으로 의존성 주입은 다시말해 직접 코드를 부여하는게 아닌, 컨테이너가 연관관계를 규정하는 것으로, 이는 직접적인 연관관계가 발생되지 않으므로 클래스들의 변경이 보다 자유로워집니다.

 

 * DI 기능

 

1. setter

 

해당 클래스의 setter메소드에 의존성 주입을 통하여 메서드를 호출합니다.

 

XML

<beans>
    <bean id="airpod" class="com.spring.test.Airpod">
		<property name="name">
			<value>Apple</value>
		</property>
	</bean>
	
	<bean id="buzz" class="com.spring.test.Buzz">
		<property name="name">
			<value>Samsung</value>
		</property>
	</bean>
</beans>

 

Interface

package com.spring.test;

public interface Earphone {
	public void volumeUp();
	public void volumeDown();
	public void nextMusic();
	public void previousMusic();
}

 

class

package com.spring.test;

public class Airpod implements Earphone {
	private String name; //제조사이름
	
	@Override
	public void volumeUp() {
		System.out.println("Airpod 소리+1");
	}

	@Override
	public void volumeDown() {
		System.out.println("Airpod 소리-1");
		
	}

	@Override
	public void nextMusic() {
		System.out.println("Airpod 노래+1");
	}

	@Override
	public void previousMusic() {
		System.out.println("Airpod 노래-1");
	}
	
	public void setName(String name) {
		this.name = name;
	}

	public String getName() {
		return name;
	}

	@Override
	public String toString() {
		return "Airpod [name=" + name + "]";
	}
	
	
}
package com.spring.test;

public class Buzz implements Earphone {
	private String name;
	
	@Override
	public void volumeUp() {
		System.out.println("Buzz 소리+1");
	}

	@Override
	public void volumeDown() {
		System.out.println("Buzz 소리-1");
	}

	@Override
	public void nextMusic() {
		System.out.println("Buzz 음악+1");
	}

	@Override
	public void previousMusic() {
		System.out.println("Buzz 음악-1");
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "Buzz [name=" + name + "]";
	}

	
}

 

test(client)

package com.spring.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");
		
		Earphone ear = (Earphone)factory.getBean("buzz");
		ear.volumeUp();
		ear.volumeDown();
		ear.nextMusic();
		ear.previousMusic();
		
		System.out.println(ear);
		
		factory.close();
	}
}

 

Earphone이라는 인터페이스를 만들고, 상속받을 airpod, buzz클래스를 생성합니다.

airpod, buzz클래스에 제조사(name)이라는 변수를 필드에 선언하고, setter, getter메소드를 생성합니다.

xml로 돌아와서 bean태그의 property 태그에서 각자 클래스 객체의 name 속성에 value태그의 값으로 초기화합니다.

마지막으로 test(client)클래스에서 GenericXmlApplicationContext클래스를 이용해 applicationContext.xml을 설정하고 id인 airpod 또는 buzz로 접근하여 메서드를 호출합니다.

 

출력결과입니다.

 

 - airpod인 경우

 

 

- buzz인 경우

 

toString 메소드를 통해 name의 값을 확인 할 수 있습니다.

 

2. 생성자

 

해당 클래스의 생성자에 의존성 주입을 통하여 메서드를 호출합니다.

(이번에는 필요한 부분만 편집하여 올리겠습니다.)

 

XML

<beans>
	<bean id="airpod" class="com.spring.test.Airpod">
 		<constructor-arg value="Apple"></constructor-arg>
 	</bean>
 	<bean id="buzz" class="com.spring.test.Buzz">
 		<constructor-arg value="Samsung"></constructor-arg>
 	</bean>
</beans>

 

class

public Airpod(String name) {
	this.name = name;
}

 

public Buzz(String name) {
	this.name = name;
}

 

test(client)

 

package com.spring.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");
		
		Earphone ear = (Earphone)factory.getBean("buzz");
		ear.volumeUp();
		ear.volumeDown();
		ear.nextMusic();
		ear.previousMusic();
		
		System.out.println(ear);
		
		factory.close();
	}
}

 

setter와 마찬가지로 방법은 거의 비슷하나 인터페이스를 구현한 클래스 부분에서 setter메소드로 받을지, 파라미터가 있는 생성자로 받을지에 따라 나뉩니다.

xml파일을 보면 아까는 property를 통해 코드를 풀어나간 반면, 생성자는 constructor-arg를 통해 코드를 전개했습니다.

 

출력결과에는 큰 차이가 없으므로 생략하겠습니다.

 

 * 정리

 

 - 의존성 주입은 스프링 컨테이너가 클래스와 클래스 사이의 연관관계를 규정한다.

 - 의존성 주입의 특징은 결합도를 통해 클래스의 변경을 보다 유연하게 조정할 수 있다.

 - 의존성 주입은 크게 setter, 생성자를 통해 주입할 수 있다.

 

 

출처 : 자바 웹을 다루는 기술

'코딩 > Spring' 카테고리의 다른 글

Spring 스프링을 사용하는 이유  (0) 2020.08.20
Spring Lombok  (0) 2020.08.18
Spring AOP 관점 지향 프로그래밍 Annotation  (0) 2020.08.14
Spring AOP 관점 지향 프로그래밍  (0) 2020.08.13
Spring context:component-scan  (0) 2020.08.11
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기