[4-1] 컴포넌트 스캔과 자동 의존관계 설정

ohun·2022년 5월 31일
0

Spring 입문

목록 보기
12/16

컴포넌트 스캔과 자동 의존관계 설정

회원 컨트롤러(MemberController)를 구현하고, 이 때 회원 서비스(MembeerService)와 회원 리포지토리(MemberRepository)를 사용할 수 있도록 의존관계를 준비한다.

회원 컨트롤러에 의존관계 추가

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;
    }
}
  • 생성자에 @AutoWired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI(Dependency Injection), 의존성 주입이라고 한다.
  • 이전 글까지의 테스트에서는 개발자가 직접 주입했고, 여기서는 @AutoWired 에 의해 스프링이 주입해준다.
  • 이후 실행하면 아래와 같은 오류가 발생한다.

    Parameter 0 of constructor in hello.hellospring.controller.MemberController required a bean of type 'hello.hellospring.service.MemberService' that could not be found

    Consider defining a bean of type 'hello.hellospring.service.MemberService' in your configuration.

  • 원인은 memberService 가 스프링 빈으로 등록되어 있지 않아서!

회원 서비스 스프링 빈 등록

@Service
    public class MemberService {

        private final MemberRepository memberRepository;

        @Autowired
        public MemberService(MemberRepository memberRepository) {
            this.memberRepository = memberRepository;
        }
}
  • memberService 클래스 위에 @Service 어노테이션을 달아줘서 스프링 컨테이너에 memberService 를 등록해준다.
  • 이제 컨트롤러와 서비스가 @AutoWired 로 연결되어서, memberController 가 생성 될 때 스프링 빈에 등록되어 있는 memberService 객체를 가져다가 넣어준다! 이게 바로 Dependency Injection 이다. (스프링이 주입~)
  • memberRepository 도 마찬가지로, 구현체인 MemoryMemberRepository 클래스 위에 @Repository 어노테이션을 달아준다.
  • MemberService 생성자 위에도 @AutoWired 어노테이션을 달아서 memberRepository 와 Service 를 연결해준다.
  • 이렇게 해서 정형화된 패턴을 만들어준다.
    • controller 로 외부 요청을 받기, service 에서 비즈니스 로직 만들기, repository 에서 데이터를 저장하기

쉽게 정리하면?

memberController 생성 → 스프링 컨테이너에서 @Controller 확인 후 스프링 컨테이너에 등록하면서 생성자 호출 → 이 때 @AutoWired 확인해서 memberController 가 memberService 를 필요로 한다는 사실 확인하여 컨테이너에 있는 memberService 를 넣어준다.

여기서 service 와 repository 간에도 같은 과정 반복. 단지 memberRepository 가 아니라 구현체인 memoryMemberRepository 가 대상이다.


컴포넌트 스캔 원리

  • @Component 어노테이션이 있으면 스프링 빈으로 자동 등록된다.
  • @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다.
  • @Component 를 포함하는 다음 어노테이션도 스프링 빈으로 자동 등록된다.
    • @Controller
    • @Service
    • @Repository
  • 스프링 빈 등록은 @Component , 연결은 @AutoWired !

But, 아무 패키지의 파일에나 등록한다고 스프링 컨테이너에서 스캔 가능한 것은 아님!

기본적으로 Application 이 속한 패키지 하위 경로에서만 가능하다.

참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.
무슨 말? 만약 memberService 이외에 orderService 가 있어서 memberRepository 를 요구할 경우 새로운 memberRepository 가 아니라 같은 인스턴스를 제공한다.

profile
공부 중입니다.

0개의 댓글