★ 9. 컴포넌트 스캔과 자동 의존관계 설정 | @Controller, @Autowired, @Service, @Repository
1. 회원 컨트롤러에 의존관계 추가
- 스프링 빈을 등록하고, 의존관계 설정하기
- Member Controller가 Member Service와 Member Repository를 사용할 수 있게 의존관계를 준비하자
- Controller와 Service가 연결되는걸 의존한다고 한다
MemberController
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;
}
}
@Controller
@Controller 어노테이션이 있으면 Spring이 처음 실행될때 Spring 통에 해당 MemberController 객체를 생성해서 통에 넣어두고 Spring이 관리한다.
이걸 스프링 컨테이너에서 Spring bean이 관리된다 라고 표현한다.
스프링 컨테이너가 관리하면서 Spring과 관련된 기능들이 동작된다. (예 : @GetMapping, @PostMapping 등)
@Autowired
- Autowired : 연결한단 뜻.
- Service를 가져다 쓸때 New로 생성해서 사용해도 된다. 하지만 스프링을 사용할땐 스프링 컨테이너에 등록하고 받아쓰게 바꿔야한다
- 생성자에 @Autowired가 있으면 Spring이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다
- 이렇게 객체 의존관계를 외부에서 넣어주는것을 DI (Dependency Injection) 의존성 주입이라 한다.
- 이전 테스트에서는 개발자가 직접 주입했고, 여기선 @Autowired 에 의해 스프링이 주입해준다
@Service
- @Autowired로 MemberController에 MemberService와 의존관계를 주입했을때를 오류가 발생한다.
- 스프링 컨테이너에 MemberService가 없기 때문이다. 이럴때 쓰는것이 @Service 어노테이션 이다.
- @Service 넣어줘야 Spring이 실행될때 Spring이 스프링 컨테이너에 Service를 등록해준다
package hello.hellospring.service;
import org.springframework.stereotype.Service;
@Service
public class MemberService {
...
}
@Repository
- @Service와 마찬가지로 Repository에도 @Repository 어노테이션을 등록해줘야한다.
package hello.hellospring.repository;
import org.springframework.stereotype.Repository;
@Repository
public class MemoryMemberRepository implements MemberRepository{
...
}
Controller, Service, Repository이 3개가 정형화된 패턴이다
Controller를 통해서 외부 요청을 받고 Service에서 비지니스 로직을 만들고 Repository에서 Data를 저장한다.
위 사진을 보면 Controller와 Service를 연결시켜 줘야하는데 연결시켜줄때 @Autowired 를 사용한다.
그럼 MemberController가 생성될때 Spring Bean에 등록되어 있는 MemverService 객체를 가져다가 MemberController에 넣어준다
이게 바로 DI (Dependency Injection) 의존성 주입 이다. Spring이 넣어주는거다. 밖에서 넣어주는 거다.
또 Service에는 Repository가 필요하다.
@Autowired로 Repository를 연결해 놓으면 Spring이 실행될때 너는 Repository가 필요하구나 하면서
MemberService를 스프링 컨테이너에 등록할때 Repository도 함께 스프링 컨테이너에 넣어준다.
package hello.hellospring.service;
import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository)
{
this.memberRepository = memberRepository;
}
}
스프링 빈을 등록하는 2가지 방법
- 컴포넌트 스캔과 자동 의존관계 설정 (윗 설명 글들)
- 자바 코드로 직접 스프링 빈 등록하기 (다음 게시물에..)
컴포넌트 스캔과 자동 의존관계 설정
- @Component : 어노테이션이 있으면 스프링 빈으로 자동 등록된다
- @Controller: 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔 때문이다.
- @Component안에 포함되어 있는 어노테이션도 스프링 빈으로 자동 등록된다
- @Controller
- @Service
- @Repository
- @Controller, @Service, @Repository 는 사실 @Component안에 모두 포함되어있다.
- 그래서 컴포넌트 스캔이라한다. Spring이 실행될때 Spring이 Component 연관된 어노테이션들을 모두 스캔한다.