Skip to content

Latest commit

 

History

History
156 lines (94 loc) · 6.83 KB

00.InversionOfControl.md

File metadata and controls

156 lines (94 loc) · 6.83 KB

Inversion Of Control, Dependency Injection Overview

스프링에서는 객체를 생성하고 관리하는 Object Factory가 있습니다. Object Factory는 annotation과 configuration File을 기반으로 객체를 전달합니다.

1. Spring Container

스프링 컨테이너는 두 중요한 역할을 수행합니다.

  1. 객체를 생성하고 관리하는 역할 ( Inverion Of Control )

  2. 객체 의존성 주입 ( Dependency Injection )

  • Inversion Of Control

    객체가 자신과 함께 작동하는 객체를 생성자, 팩토리 메소드의 인자, 프로퍼티로만 받는 프로세스가 IoC입니다. 따라서 IoC로 구현한 Application은 제어권이 사용자가 아닌 Framework에 있습니다.

    Spring에서는 IoC를 Spring Container를 통해 구현했습니다. Spring Container의 최상위 인터페이스는 BeanFactory이며 BeanFactory는 Bean을 관리합니다. 하지만 Spring에서 IoC Container는 Bean 관리 이외에 많은 역할을 수행하는데 이것이 BeanFactory를 상속받은 ApplicationContext입니다.

    • Spring Beans

      여기서 스프링 컨테이너가 생성하고 관리하고 Application의 토대를 이루는 자바 객체를 스프링에서 Spring Beans 라고 부릅니다. 스프링 빈은 Spring IoC Container에 의해 생성되고, 조립되고, 관리됩니다. Bean과 Bean간의 종속성은 컨테이너에서 사용되는 Configuration Meta Data중 하나일 뿐입니다. Spring IoC Container에 의해 관리되지 않는 객체는 Application의 수많은 객체들 중 하나일 뿐입니다.

  • Dependency Injection

    Dependency Injection은 의존성의 책임을 다른 객체에 위임하는 이론을 말합니다. 조금 더 직접적으로 말한다면 DI는 의존관계를 외부에서 결정하고 주입하는 것을 말합니다.

    여기서 의존관계라는 표현 의미를 살펴보겠습니다. A라는 클래스에서 한 메소드에 B라는 클래스의 메소드를 사용하고 있습니다 .이때 B클래스가 변하면 A 클래스에도 영향이 미칩니다.

    class helloPrint {
    	private EnglishHello englishHello;
    	
    	public helloPrint () {
    		this.englishHello = new EnglishHello();
    	}
    	
    	public String hello() {
    		return englishHello.hello() + ", My Name is Ted" ;
    	} 
    }
    
    class EnglishHello {
    	
      // EnglishHello의 hello()가 annyeong()으로 변경된다면 helloPrint 수정 필요
    	public String hello() {
    		return "Hello";
    	}
    }

    위 예제에서 EnglishHello의 hello()가 한국어로 변경되었다면 EnglishHello를 의존하는 helloPrint 클래스는 많은 수정이 필요합니다. 따라서 이는 강한 결합도를 보여준다고 할 수 있습니다.

    위 결합도를 낮추기 위해서는 Interface를 활용하여 추상화하여 구현하면 결합도를 낮출 수 있습니다.

    class helloPrint {
    	private Hello hello;
    	
    	public helloPrint () {
    		this.hello = new EnglishHello();
    	}
    	
    	public String hello() {
    		return hello.hello();
    	} 
    }
    
    interface Hello {
    	
    	public String hello();
    }
    
    class KoreanHello implements Hello {
      
      @Override
      public String Hello() {
        return "안녕하세요.";
      }
    }
    
    class EnglishHello implements Hello{
    	
    	public String hello() {
    		return "Hello";
    	}
    }

    Interface를 활용함으로써 우리는 결합도를 느슨하게 유지할 수 있습니다.

    DI는 여기서 조금더 나아갑니다. 위 코드에서 구현체를 변경하기 위해서 직접 HelloPrint 클래스 코드를 수정해야합니다. 하지만 DI는 팩토리 메소드나 인수, constructor를 통해서 인스턴스가 반환된 후 해당 클래스의 의존성을 주입합니다. 그러므로 HelloPrint 클래스는 Dependercis의 위치나 클래스를 알지 못합니다. DI를 구현하기 위해서는 반드시 외부 객체에서 의존성이 정의되어야 합니다. Spring은 이런 DI를 간단히 구현할 수 있는 방법과 도구를 제공합니다.

    위 사항을 정리하면 의존 관계 주입을 충족시키기 위해서 다음과 같은 조건이 필요합니다.

    1. 클래스 모델이나 코드에는 런타임 시점의 의존관계가 들어나지 않는다. 따라서 인터페이스만 의존하고 있어야 한다.
    2. 런타임 시점의 의존관계는 컨테이너나 팩토리 같은 제 3의 존재가 결정한다.
    3. 의존관계는 사용할 Object에 대한 Refrence를 외부에서 주입함으로서 만들어진다.

    Spring에서 의존성을 주입하는 방법은 크게 3가지입니다.

    1. Setter
    2. Constructor
    3. Autowired
  • Application Context

    스프링 컨테이너는 일반적으로 ApplicationContext로 알려져 있습니다. ApplicationContext는 interface이며 Application을 구현한 구현체의 종류는 다음과 같습니다.

    • Application Context

      1. ClassPathXmlApplicationContext : Configuration xml을 classpath에서 찾는다.

      2. FileSystemXmlApplicationContext : FileSystem에서 Configuration 설정을 load

      3. AnnotationConfigApplicationContext

      4. GenericWebApplicationContext

      5. 기타 등등....

    Application Context는 Application을 위한 설정파일을 구성하기위한 인터페이스입니다. ApplicationContext는 다음을 제공합니다.

    1. Bean Factory : Application 구성요소를 접근, ListableBeanFactory에서 상속
    2. 일반적인 방식으로 file을 로드하는 기능, ResourceLoader Interface에서 상속
    3. 이벤트를 등록하는 기능, ApplicationEventPublisher Interface에서 상속
    4. 국제화를 지원하는 메시지를 해결하는 기능, MessageSource interface에서 상속
  • Bean Factory

    Spring이 제공하는 IoC Continer 두 종류중 하나입니다. Spring 빈 컨테이너에 접근하기 위한 root interface입니다.

  • Bean Factory VS ApplicationContext

    Bean Factory와 ApplicationContext의 주요 차이점은 다음과 같다.

    1. ApplicationContext는 BeanFactory의 bean 생성, 관리 기능에 추가 기능을 제공
    2. ApplicationContext는 설정파일에서 정의한 Bean을 미리 로드하고 라이프사이클을 관리합니다. 즉 getBean()을 호출하기 전에 모든 Bean을 생성, 관리합니다. 반면 BeanFactory는 getBean을 호출하면 그 때 Bean 라이프사이클이 시작됩니다.

1-1. Spring IoC Container Configuration

  1. XML Configuration File ( Legacy )
  2. Java Annotations
  3. Java Source Code