package hello.hellospring.controller;
import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller // annotation 역할 : spring bean으로 해당 클래스를 spring-container에서 관리
public class MemberController {
private final MemberService memberService;
@Autowired//Controller 와 Service 간의 연결 수행하는 어노테이션
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
}
생성자에 @AutoWired가 있으면 스프링이 연관된 객체(여기서는 MemberService)를 찾아서 알아서 연결해준다. 이런 식으로 외부에서 객체 의존관계를 주입해주는 것을 DI라고 한다. 이전 테스트 케이스 작성에서는 개발자가 직접 코딩으로 넣는 방식이었고, 여기서는 @AutoWired에 의해 스프링이 직접 의존관계를 주입해준다.
만약 Controller만 스프링 빈으로 등록하면 아래와 같은 에러가 발생한다.
이는 스프링 컨테이너가 MemberController는 찾았지만 MemberService는 찾지 못해서 발생했다.
이를 해결하기 위해 우리는 Service,Repository 객체도 스프링 빈으로 등록해야 한다.
서비스와 레포지토리 객체 스프링 빈 등록하기
@Service//서비스 스프링 빈으로 등록
public class MemberService {
private final MemberRepository memberRepository;
@Autowired
public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
}
@Repository//레포지토리 스프링 빈으로 등록
public class MemoryMemberRepository implements MemberRepository{}
Component Scan 원리
@Component 어노테이션이 붙어있으면 스프링 빈에 자동 등록된다.
@Service, @Repository, @Controller는 @Component를 가지고 있는 어노테이션들이다. 그래서 스프링 빈에 자동 등록된다.
@ SpringBootApplication 어노테이션은 @ComponentScan이라는 어노테이션을 포함하고 있다.
@ComponentScan 어노테이션은 해당 클래스와 같은 Level의 패키지의 하위 클래스들에 대해 컴포넌트 스캔을 진행하면서 객체를 스프링 빈에 등록한다.
참고로, 스프링은 스프링 컨테이너에 스프링 빈을 등록할때 기본으로 싱글톤으로 등록한다.(유일하게 하나만 등록해서 그걸 공유하는 방식) 따라서 동일한 스프링 빈이라면 동일한 인스턴스이다.
자바 코드로 직접 스프링 빈 등록하기
회원 서비스와 회원 레포지토리의 @Service, @Repository, @Autowired를 삭제하고 나서 진행합니다.
hello.hellospring 패키지 밑에 바로 SpringConfig 클래스를 아래와 같이 작성합니다.
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();
}
}
SpringConfig가 직접 스프링 등록하기 위한 클래스임을 설정하는 @Configuration 어노테이션을 달아준다.
이후, 각각의 MemberService, MemberRepository에 대해서 @Bean 어노테이션을 달아주고 리턴 값으로 자기자신의 생성자 또는 메모리 구현체를 넘긴다.
언제 자바 코드로 직접 스프링 빈 등록하는 방식이 컴포넌트 방식보다 유리할까?
대부분의 정형화된 실무에서 사용하는 구조는 편리한 컴포넌트 방식으로 스프링 빈을 등록하지만, 정형화된 틀이 없거나 상황에 따라 구현 클래스를 직접 수정해야 하는 일이 있는경우에는 SpringConfig로 직접 스프링 빈을 등록하는게 유리하다.
예를들어 해당 프로젝트 DB대신 메모리 레포지토리를 사용하고 있기에 추후에 변경할 예정이므로 컴포넌트 스캔 방식보다 SpringConfig 방식이 좀 더 유리하다.
You might also like...
9월
06
<Spring> AOP 적용 시 주의 사항들
본 포스팅에서는 spring AOP를 사용할 경우 발생 할 수 있는 문제들에 대해서 알아보고 이를 어떻게 하면 해결할 수 있는지 확인해
6 min read
8월
30
<Spring> @Transactional readOnly 값에 의한 DataSource로의 요청 분산 시키기
본 포스팅은 여러개의 주제로 구성되어 스프링부트 환경에서 DataSource로의 요청을 분산시키는 여러 방법들에 대해서 알아볼 예정입니다. DataSource 분산 처리는 아래의 두
8 min read
12월
29
<Spring> AOP 발전과정 살펴보기 1
스프링 AOP는 공통적인 횡단 관심사 영역을 프록시를 통해 한 곳에 모아서 Aspect로 관리하는 프로그래밍 패러다임이다. 공통 관심사의 대표적인 예는 로깅,
11 min read
12월
12
<Spring> Spring MVC의 DispatcherServlet 핵심로직 들여다보기
Spring MVC를 공부해보니 DispatcherServlet이라는 클래스가 맡고 있는 역할이 중요하다는것을 알게 된다.해당 포스트는 DispatcherServlet을 중심으로 어떻게 Spring MVC가 HTTP 요청을
7 min read
5월
26
<Spring> 우리는 왜 MVC를 사용할까?
MVC의 등장 배경자바의 JSP와 서블릿만을 이용해서 웹서비스를 개발해보신 경험이 있으신가요?JSP의 경우 아래와 같은 코드 구조를 가지게 됩니다.굉장히 간단한