본문 바로가기
Dev/Spring

[스프링 프레임워크 입문] IoC

by dev_jsk 2020. 11. 17.
728x90
반응형

IoC (Inversion of Control)

제어의 역전, 내가 사용할 의존성을 내가 만드는 것이 아닌 외부의 다른 누군가가 만들어 주는 것

 

예제

// OwnerController.java
@Controller
class OwnerController {
  private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
  private final OwnerRepository owners;
  private VisitRepository visits;
  
  public OwnerController(OwnerRepository clinicService, VisitRepository visits) {
    this.owners = clinicService;
    this.visits = visits;
  }

  @PostMapping("/owners/new")
  public String processCreationForm(@Valid Owner owner, BindingResult result) {
    if (result.hasErrors()) {
      return VIEWS_OWNER_CREATE_OR_UPDATE_FORM;
    }
    else {
      this.owners.save(owner);
      return "redirect:/owners/" + owner.getId();
    }
  }

OwnerController를 보고 IoC를 이해해보자

OwnerController의 생성자를 보면 OwnerRepositoryVisitRepository가 사용되는 것을 볼 수 있다. 또한 생성자의 인수로 넘겨준 객체의 함수 사용도 가능하다.

 

일반적으로 객체의 함수나 변수에 접근이 가능하려면 해당 객체를 생성하여 사용해야 한다. 그렇지만 코드를 보면 객체를 생성하는 구문은 존재하지 않는다. 그러면 어디서 객체를 생성하는 걸까?

 

OwnerControllerTest를 보면 알 수 있다.

// OwnerControllerTest.java
@WebMvcTest(OwnerController.class)
class OwnerControllerTests {
  private static final int TEST_OWNER_ID = 1;
  
  @Autowired
  private MockMvc mockMvc;
  
  @MockBean
  private OwnerRepository owners;
  
  @MockBean
  private VisitRepository visits;

@MockBean 어노테이션(Mock 객체를 만들어 Bean으로 등록)을 사용하기 때문에 해당 객체의 함수나 변수에 접근이 가능하다.

그렇기 때문에 스프링의 Bean으로 등록되면 OwnerController 생성 시 해당 타입의 객체를 주입해준다. 이 동작은 스프링 수행한다.

※ 여기서 Bean이란 스프링이 관리하는 객체를 말한다.

IoC Container

빈을 만들고 빈들 사이의 의존성을 엮어주고, 그 빈들을 제공하는 역할

의존성 주입은 IoC Container 안에 있는 객체들 끼리만 가능하다.

Bean

IoC Container가 관리하는 객체

Bean 등록하는 방법

  • Component Scanning
    • @Component
      • @Repository
      • @Service
      • @Controller
      • @Configuuration
  • XML이나 Java 설정 파일에 등록

Java 설정파일 예제

// SampleConfig.java

@Configuration
public class SampleConfig {
  @Bean
  public SampleController sampleController() {
    return new SampleController();
  }
}

// SampleController.java

// @Controller --> SampleConfig 클래스에서 직접 Bean으로 등록했기 때문에 어노테이션 사용할 필요 없다.
public class SampleController {}

Bean 꺼내 쓰는법

  • @Autowired, @Inject
  • ApplicationContext에서 getBean()으로 직접 꺼내 사용

의존성 주입

객체를 외부로부터 주입해주는 것

의존성 주입하는 방법

  • 생성자 이용
  • 필드 이용
  • Setter 이용

OwnerController에 PetRepository 주입하기

// OwnerController.java

@Controller
class OwnerController {
  // 1. 필드
  @Autowired
  public PetRepository petRepository;
  
  // 2. 생성자
  public final OwnerRepository owners;
  public final PetRepository petRepository;
  
  public OwnerController(OwnerRepository clinicService, PetRepository petRepository) {
    this.owners = clinicService;
    this.petRepository = petRepository;
  }
  
  // 3. Setter
  public PetRepository petRepository;
  
  @Autowired
  public void setPetRepository(PetRepository petRepository) {
    this.petRepository = petRepository;
  }
}
728x90
반응형

댓글