스프링 컨테이너에 빈을 등록하는 이유
: 객체를 다루는 일반적인 방법은 개발자가 프로그램 로직 상 필요한 객체를 그때그때 직접 생성하고 필요한 메서드를 호출하는 것이다.
자바의 경우, new
키워드를 통해 필요한 곳에 인스턴스를 생성하는 로직을 넣는다.
하지만 스프링에서는 클래스들의 인스턴스(객체)를 일일이 개발자가 다루는 것이 아니라 스프링에게 관리를 맡긴다. 이것이 스프링의 주요 특징 중 하나인 IoC(Inversion of Control)이다.
IoC는 제어의 역전이라고 하며, 쉽게 말해 제어의 흐름을 바꾸는 것이다.
필요한 객체를 개발자가 직접 생성하는 것이 아니라 스프링이 생성해 놓은 객체를 가져와서 쓰게 된다.
IoC (Inversion of Controler): 제어의 역전, 객체를 개발자가 아닌 외부(스프링 컨테이너)에서 생성, 관리
이 때 스프링이 객체들을 미리 생성해 관리하는 공간을 스프링 컨테이너라고 하며, 이렇게 스프링에 의하여 생성되고 관리되는 자바 객체를 스프링에서는 빈(Bean)이라고 한다.
스프링 컨테이너 (Spring Container): 스프링에서 자바 객체들을 관리하는 공간
스프링 빈 (Spring Bean): 스프링에 의하여 생성되고 관리되는 자바 객체
회원 컨트롤러가 회원서비스와 회원 리포지토리를 사용할 수 있도록 의존관계를 준비한다.
package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class MemberController {
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
}
@Repository
public class MemoryMemberRepository implements MemberRepository {}
memberService와 memberRepository가 스프링 컨테이너에 스프링 빈으로 등록된다.
스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다.
(유일하게 하나만 등록해서 공유한다.)
따라서 같은 스프링 빈이면 모두 같은 인스턴스이다.
package hello.hellospring;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
- DI에는 필드 주입, setter 주입, 생성자 주입 3가지 방법이 있다.
- 의존 관계가 실행중에 동적으로 변하는 경우는 거의 없으므로 보통 생성자 주입을 권장
- 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
- @Autowired를 통한 DI는 helloController, memberService 등과 같이 스프링이 관리하는 객체에서만 동작한다.