본문 바로가기
프로젝트/도서관리 프로젝트

도서관리 프로젝트[5] IoC 제어의 역전, 인터페이스(interface), @Primary

by CodeMango 2023. 6. 22.

제어의 역전(Inversion of Control)

 

스프링 컨테이너가 필요에 따라 개발자 대신 Bean들을 관리(제어)해주는 행위

 

 

일반적인 상황에서는 개발자가 직접 객체를 제어해야 했다. new 연산자를 통해 객체를 생성하고, 객체의 의존성을 맺어주고, 초기화를 해주고 등등...

 

하지만 Spring 에서는 xml파일 또는 어노테이션 방식으로 스프링 컨테이너에 Bean(객체)를 등록하기만 하면, 스프링 컨테이너에서 Bean의 생명주기(생성 -> 의존성 설정 -> 초기화 -> 소멸)를 전부 관리해준다.

 

즉, 객체에 대한 제어권이 컨테이너로 역전되기 때문에 제어의 역전이라고 하는 것이다.

장점

  • 개발자는 객체 관리에 덜 신경쓸 수 있게 되어 다른 부분에 더 집중할 수 있게 됨
  • 약한 결합(참고 링크)을 이용하여 객체 간 의존 관계를 쉽게 변경할 수 있음

결론적으로 코드의 재사용성과 유지보수성을 높인다.

정리

  • Spring에서는 제어의 역전을 지원하여, 필요에 따라 개발자대신 스프링 컨테이너가 객체(Bean)들을 제어해준다.
  • 스프링 컨테이너는 Bean들의 생명주기(생성 -> 의존성 설정 -> 초기화 -> 소멸)을 관리하며, 필요에 따라 객체 간 의존성 주입을 해준다.
  • 제어의 역전은 의존성 주입의 상위 개념이다.
  • 제어의 역전은 코드의 재사용성과 유지보수성을 높인다.

 

인터페이스(Interface)

인터페이스를 사용하여 코드를 작성해보겠습니다.

인터페이스 개념은 아래 포스트를 참고하시면 됩니다. 

https://coday.tistory.com/40

 

 

@Primary

컨테이너가 BookService를 만들어줄 때 BookMemoryRepository와 BookMySqlRepository 중 하나를 선택해서 넣어주는 과정을 의존성 주입(Dependency Injection)이라고 하는데, 둘 중 무엇을 넣어줄지 결정하기 위해 @Primary를 사용합니다.

 

 

BookController

package com.group.libraryapp.controller.book;

import com.group.libraryapp.service.book.BookService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class BookController {

    private final BookService bookService;

    //생성자 만들어서 스프링빈 주입받기
    public BookController(BookService bookService) {
        this.bookService = bookService;
    }

    @PostMapping("/book")
    public void saveBook() {
        bookService.saveBook();
    }
}

 

BookService

package com.group.libraryapp.service.book;

import com.group.libraryapp.repository.book.BookMemoryRepository;
import com.group.libraryapp.repository.book.BookMySqlRepository;
import com.group.libraryapp.repository.book.BookRepository;
import org.springframework.stereotype.Service;

@Service
public class BookService {

    private final BookRepository bookRepository;

    //생성자를 통해 레포지토리 주입받기
    public BookService(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    public void saveBook(){
        bookRepository.saveBook();
    }
}

 

BookMySqlRepository

package com.group.libraryapp.repository.book;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;
@Primary
@Repository
public class BookMySqlRepository implements BookRepository {
    @Override   //ctrl+ o
    public void saveBook() {
        System.out.println("sql");

    }
}

 

BookMemoryRepository

package com.group.libraryapp.repository.book;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
//@Primary
@Repository
public class BookMemoryRepository implements BookRepository {

    //원래는 아래와 같이 썼음
    //private final List<Book> books = new ArrayList<Book>();

    @Override
    public void saveBook(){
        //books.add(new Book());
        System.out.println("memory");
    }
}

 


위와 같이 코드를 진행하고 포스트맨에서 호출해주면 콘솔창에 "sql"이 출력됩니다.

@Primary 어노테이션을 BookMySqlRepository 에 달아주었기 때문입니다! 

 

콘솔창

댓글