스프링의 대표적인 기능중 하나인 제어 역전(IoC)와 의존성 주입(DI)을 알아보겠습니다. 제어 역전이란 객체 생성, 관계설정, 사용, 제거 등 오브젝트 전반에 걸친 모든 제어권을 애플리케이션이 갖는게 아니라 프레임워크의 컨테이너에게 넘기는 개념을 말합니다.
의존성 풀은 자바 개발자라면 익숙한 방식이다. 의존성 풀은 JNDI API를 이용하여 컴포넌트를 조회하는 방식입니다.아래 코드를 봅시다.
import org.springframework.context.ApplicatoinContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class DependencyPool {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/app-context.xml");
MeessageRenderer mr = ctx.getBean("renderer", MessageRenderer.class);
mr.render();
}
}
코드를 보면 ClassPathXmlApplicationContext 인스턴스를 이용하여 스프링 프레임워크가 app-context.xml을 읽고, xml파일에 정의되어 있는 Bean(객체)을 생성합니다.그리고 getBean() 메서드를 이용하여 스프링이 생성해놓은 renderer Bean을 참조합니다.그리고 render() 메서드를 사용하여 Hello World!를 출력합니다.
의존성 룩업은 의존성 풀과 동일해 보이지만 약간 다릅니다. 의존성 풀은 JNDI API를 이용하여 컨테이너에게 객체를 조회했지만, 의존성 룩업은 JNDI API를 사용하지 않고 바로 컨테이너에게 객체를 조회합니다.
말 그대로 의존성을 주입하는 방식입니다.예를 들어 A 클래스가 B 클래스의 인스턴스를 생성하여 사용한다면, 인스턴스를 A 클래스 내에서 직접 생성하는 것이 아닌 스프링 프레임워크가 인스턴스를 생성하여 A 클래스의 B타입 인스턴스 변수에 주입해줍니다.
의존성 주입의 방법에는 두가지가 있습니다. 바로 생성자 주입과 수정자 주입입니다.
생성자 주입은 클래스의 생성자를 이용하여 의존성을 제공하는 방식입니다. 어떤 클래스가 의존성을 매개변수로 생성자를 선언했다면, 스프링 프레임워크는 해당 클래스의 인스턴스를 초기화할 때 필요한 의종성을 주입합니다.
public class ConstructorInjection {
private Dependency dependency;
// 생성자의 매개변수를 의존성으로 선언
public ConstructorInjection(Dependency dependency) {
this.dependency = dependency;
}
}
생성자 주입은 해당 인스턴스를 생성하려면 강제적으로 의존성을 주입해야 합니다.
수정자 주입은 클래스에 수정자 메서드를 이용하여 의존성을 주입합니다. 수정자는 스프링 프레임워크가 관리할 수 있도록 의존성을 노출시킵니다.
public class SetterInjection {
private Dependency dependency;
// 수정자를 통해 의존성을 노출
public void setDependency(Dependency dependency) {
this.dependency = dependency;
}
}
수정자 주입은 의존성 없이도 인스턴스를 생성할 수 있으며, 해당 수정자를 호출하여 의존성을 나중에 주입할 수 있습니다. 수정자 주입은 가장 널리 사용되며 구현하기 가장 쉬운 의존성 주입 방식입니다.