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...
5월
26
<Spring> 우리는 왜 MVC를 사용할까?
MVC의 등장 배경자바의 JSP와 서블릿만을 이용해서 웹서비스를 개발해보신 경험이 있으신가요?JSP의 경우 아래와 같은 코드 구조를 가지게 됩니다.굉장히 간단한
8 min read
5월
20
<Spring> 서블릿 사용해보기
해당 포스팅은 스프링 배우기 전 알아두면 좋은 개념과 연속적으로 진행되는 포스팅입니다. 프로젝트 설정하기우선 https://start.spring.io/으로 접속해서 아래와
15 min read
5월
19
<Spring> 스프링 배우기 전 알아두면 좋은 개념
Web Application Server vs Web ServerWeb Server : 단순한 정적인 리소스들 화면에 뿌려줄 수 있습니다.대표적인 예로 Apache,Nginx 등이 존재합니다.
6 min read
2월
22
<Spring> 스프링에서 왜 DI가 중요할까?
우선 DI를 파보기 전에 스프링이 뭔지에 대해서 알아봅시다. 스프링이라 함은 오픈 소스의 경량 웹 프레임워크라고 정의되어있습니다.즉,개발자들이 웹 개발을
5 min read
1월
26
Springboot 프로젝트에 MS Azure MySQL 연결하기
최근 AWS 과금으로 인해서 어느 클라우드 디비를 사용할까 하다가 Azure가 학생용 요금이 따로 존재한다는 것을 보고 선택했습니다.(사실 AWS도 학생용이