이번 강의에서는 스프링 빈을 어떻게 등록하고, 의존관계가 어떻게 설정되는지 알아볼 것이다.
Spring 이 실행 될 때, Spring Container 라는 통이 하나 생긴다. 그 안에 @Controller
라는 어노테이션이 있으면, 해당 어노테이션을 가진 객체를 생성해서 Spring 에 넣어준다. 그리고 Spring 에서 관리해준다.
스프링 입문(3) 회원 관리 예제-백엔드 개발 에서 작성한 MemberController
를 기반으로 설명할 예정이다.
회원 컨트롤러(MemberController)가 회원 서비스와 회원 리포지토리를 사용할 수 있도록 의존 관계를 준비할 것이다.
MemberService
에 @Autowired
붙여주기 package com.hello.hellospring.controller;
import com.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 는 Spring container에서 MemberService를 가져온다.
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
@Autowired
가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존관계를 외부에서 넣어주는 것을 의존성 주입, DI(Dependency Injection)
이라고 한다.@Autowired
에 의해 스프링이 주입해준다.회원 서비스 스프링 빈 등록
MemberService
클래스에 @Service
어노테이션 붙여주기MemberController
안의 MemberService
에 @Autowired
를 붙여줬다고 해서, 의존성 관계가 바로 연결되지 않는다.MemberService
클래스에 @Service
어노테이션을 붙여줘야지만 스프링 빈으로 자동 등록되어 자동 의존관계가 설정되는 것이다. package com.hello.hellospring.service;
import com.hello.hellospring.domain.Member;
import com.hello.hellospring.repository.MemberRepository;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class MemberService {
private final MemberRepository memberRepository;
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Repository
public class MemoryMemberRepository implements MemberRepository {}
이제 위 세가지 과정을 통해, MemberService
와 MemberRepository
가 스프링 컨테이너에 스프링 빈으로 등록되었다.
참고 : 스프링은 스프링 컨테이너에 빈을 등록할 때, 기본적으로 싱글톤으로 등록한다. ( 유일하게 하나만 등록해서 그 객체를 공유 )
따라서 같은 스프링 빈이라면 모두 같은 인스턴스다. 설정을 통해 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하고 대부분 싱글톤을 사용한다.
스프링 빈을 등록하는 데에는 2가지 방법이 있다.
회원 컨트롤러에 의존관계 추가 에서는 컴포넌트 스캔을 통해 자동 의존관계를 등록한 것이다.
컴포넌트 스캔 원리
@Component
어노테이션이 있으면 스프링 빈으로 자동 등록된다.@Controller
, @Service
, @Repository
모두 @Component
를 포함하고 있기 때문에, 해당 어노테이션을 붙여주면 스프링 빈으로 자동 등록되는 것이다.실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다.
그리고 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하는 경우라면 설정을 통해서 직접 자바 코드로 스프링 빈을 등록한다.
해당 강의에서는, 향후 MemoryMemberRepository 를 다른 리포지토리로 변경할 예정이므로, 컴포넌트 스캔 방식 대신에 자바 코드로 스프링 빈을 설정하겠다.
이번에는 직접 자바 코드를 통해서 스프링 빈을 등록해 볼 것이다.
@Service
, @Repository
, @Autowired
어노테이션을 제거한다.SpringConfig
클래스를 만들고, 아래와 같이 코드를 작성한다.package com.hello.hellospring;
import com.hello.hellospring.repository.MemberRepository;
import com.hello.hellospring.repository.MemoryMemberRepository;
import com.hello.hellospring.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/*
@Configuration 을 통해 spring이 뜰 때 @Configuraiton을 읽고 MemberService를 스프링빈에 등록해준다.
*/
@Configuration
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
@Configuration
과 @Bean
어노테이션을 통해 스프링 빈으로 등록이 가능하다. @Configuration
을 통해 spring이 뜰 때 @Configuraiton
을 읽고 MemberService
를 스프링 빈으로 등록해준다.