Spring 핵심기술 - IoC/DI

wit_dan·2021년 11월 2일
0

Spring

목록 보기
2/2

IoC (Inversion of Control)

  • 제어의 역전

  • 의존관계에 대한 책임을 제3자에게 위임 (책임에 대한 분리)

  • 객체지향적으로 Single Responsibility Principle(단일 책임 원칙)을 지킬 수 있음

  • 예시

    1) B Interface를 구현한 B1, B2 Class가 있음

    2) A는 B의 Method를 사용하고자 함

    3) A Class에서 직접 호출

    • A가 B를 의존하고 있는 형태 (B의 로직에 따라 A가 영향을 받음)
    • B Interface의 구현 Class 중 어떤 Class를 사용해야할 지 A Class가 직접 지정을 해야함
    • 즉, A가 B의 구현에 대한 책임을 지게 됨
    • 만약 B1에서 B2로 바꾸고 싶을 경우 A의 소스를 고쳐야함

    3-1) Factory Class에서 호출 후 B의 정보를 읽어와 주입

    • Factory에서 B에 대한 return을 받아 A class 내의 b 객체에 주입
    • B1에서 B2로 바뀌더라도 Factory Class만 수정



DI (Dependency Injection)

  • 의존성 주입

  • Spring에서 IoC 역할을 하는 모듈을 Spring Container, DI Container라고 부름

  • 구체적인 의존 객체와 그것을 사용하는 주체인 클라이언트 객체를 런타임 시 연결

  • 결합도가 낮은 코드를 작성할 수 있고, 변경이 자유로움 (다양한 확장 방법 가능)

  • 조건

    1) 클래스 모델이나 코드는 인터페이스에만 의존 (런타임 시점의 의존 관계가 드러나지 않는다.)

    2) 런타임 시점의 의존관계는 Factory나 Container와 같은 제3의 존재에 의해 결정

    3) 의존관계는 사용할 객체에 대한 레퍼런스를 외부에서 제공(매개변수 등)해줌으로써 만들어짐

    // DI 위반
    // 구체적인 클래스의 존재를 A Class가 이미 알고 있음
    public class A {
    	private B b;
    	
    	public A() {
    	  b = new B_1();
    	}
    }
    
    // DI 충족
    // 객체에 대한 레퍼런스를 외부에서 제공하는 식으로 코드를 작성
    // A Class는 런타임 시점에 전달받은 인자(b)와의 의존관계 형성
    public class A {
    	private B b;
    
      public A(B b) { // B1 or B2 Class의 객체가 DI Container를 통해 주입될 예정
        this.b = b;
      }
    }



Spring IoC Container

  • Spring IoC는 일반적인 IoC 개념에 DI의 개념을 추가한 IoC/DI Container

  • Spring의 Bean Factory를 이용하여 작성한 IoC 방법

     /*
      * @Configuration: Bean Factory가 사용할 설정정보(Component Scan을 통해 Bean으로 생성)
      * @Bean: return되는 Object를 Bean으로 생성
      */
     @Configuration
     public class Factory {
       @Bean
       public A a() {
         return new A();
       }
     
       @Bean(name="b_1")
       public B b_1() {
         return new B_1();
       }
     
       @Bean(name="b_2")
       public B b_2() {
         return new B_2();
       }
     }
     
     // Client단
     // ApplicationContext.getBean을 통해 Bean 객체를 받아서 a 변수에 주입
     // getBean을 호출함으로써 객체가 생성되고 Spring Container의 Singleton으로 등록
     // [Singleton]
     // 해당 Bean이 한번도 사용되지 않아 생성되어 있지 않다면 Bean을 생성하고,
     // 한번이라도 사용되어진 Bean이라면 생성된 Bean Object를 바로 사용한다.
     public class Test {
       private A a;
     
       // [ApplicationContext 객체는 Bean 설정 방식에 따라 가져오는 방식이 다름](https://it-mesung.tistory.com/28)
       // 위의 경우엔 java를 활용하여 Bean을 등록 (Factory 클래스가 설정 파일이 됨)
       ApplicationContext context = new AnnotationConfigApplicationContext(Factory.class);
     
       a = (A) context.getBean('a'); //Bean 이름으로 가져오기
       a = (A) context.getBean(A.class); //Class로 가져오기
     }
     ```
profile
Back-End 개발자 / 기록용

0개의 댓글