스프링 컨테이너가 관리하는 자바 객체(POJO)를 빈(Bean)이라고 한다.
자바에서는 객체를 생성할 때 주로 new()
를 통해 생성하는데, 이 객체를 의미하는 것이 아니라 컨테이너에서 스스로 생성하고 관리하는 객체를 의미한다.
컨테이너에서의 관리를 통해 객체를 여러 번 생성할 필요가 없고, 공용으로 사용할 수 있다.
스프링 컨테이너는 스프링 빈의 생명 주기를 관리하며, 생성된 스프링 빈들에게 추가적인 기능을 제공하는 역할을 한다.
스프링의 3대 핵심원리인 IoC(제어의 역전), DI(의존성 주입)의 원리가 스프링 컨테이너에게 적용된다.
개발자는 new
연산자, 인터페이스 호출, 팩토리 호출 방식으로 객체를 생성하고 소멸하지만, 스프링 컨테이너는 이를 대신 해준다.
즉, 제어의 흐름을 외부에서 관리하게 된다.(IoC)
또한, 객체들과의 의존관계를 스프링 컨테이너에서 알아서 만들어준다.(DI)
스프링 빈을 등록하는 방식에는 크게 2가지가 있다.
1. 컴포넌트 스캔과 자동 의존관계 설정
2. 자바 코드로 직접 스프링 빈 등록하기
컴포넌트 스캔은 @Component
어노테이션을 명시하여 빈을 추가하는 방법이다. 클래스 위에 @Component
를 붙여서 스프링 컨테이너에 빈을 등록한다.
@Controller
컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 덕분이다.
@Component
를 포함하는 다음 어노테이션도 스프링 빈으로 자동 등록된다.
@Controller
: 스프링 MVC 컨트롤러로 인식된다.@Service
: 특별한 처리는 하지 않으나, 개발자들이 핵심 비즈니스 계층을 인식하는 데 도움을 준다.@Repository
: 스프링 데이터 접근 계층으로 인식하고 해당 계층에서 발생하는 예외는 모두DataAccessException
으로 처리한다.@Configuration
: 스프링 설정 정보로 인식하고 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.
hello-spring/src/main/java/hello/hellospring/controller/MemberController.java
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 memberReopsitory) {
this.memberRepository = memberRepository;
}
}
생성자에 @Autowired
를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다. 생성자가 1개만 있으면 @Autowired
는 생략할 수 있다.
controller와 service 연결
: MemberController 생성될 때 스프링 빈에 등록되어있는 MemberService 객체를 가져다 넣어준다.
: DI(Dependecny Injection: 의존성 주입)
service 전체 흐름도
: MemberService는 MemberRepository가 필요하다. 스프링은 MemberService를 호출할 때 @Service
보고 스프링 컨테이너에 MemberService 등록하며 생성자를 호출한다.
이때 @Autowired
가 있으면 MemberRepository가 필요하다고 판단한다.
MemberRepository 스프링 컨테이너에는 구현체로 MemoryMemberRepository가 있으므로 MemoryMemberRepository가 서비스에 주입된다.
@Reopsitory
public class MemoryRepository implements MemberRepository {}
@Autowired
는 관계를 연결해준다.@Component
어노테이션이 있으면 스프링 빈으로 자동 등록된다.@SpringBootApplication
부터 시작해, 패키지를 포함한 하위 패키지들은 스프링이 어노테이션을 찾아 스프링 빈으로 등록한다.
하위 패키지가 Application 패키지와 동일하거나 하위 패키지가 아닌 경우 컴포넌트 스캔을 하지 않는다.
@Autowired
를 통한 DI는 스프링이 관리하는 객체(helloController
, memberService
)에서만 동작한다. 사용자가 직접 생성한 객체에서는 동작하지 않는다.SpringConfig
파일 만들기hello-spring/src/main/java/hello/hellospring/SpringConfig.java
package hello.hellospring;
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();
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
스프링이 뜰때, @Configuration
을 읽고, @Bean
쓰여진 memberService 로직을 호출해 스프링 빈에 등록한다.
memberService는 생성자에서 memberRepository 를 넣어줘야 하는데, 인터페이스이므로 이의 구현체인 MemorymemberRepository를 리턴하여 넣어준다.