스프링 빈과 의존관계
컨트롤러를 통해 html 화면을 뿌리고 또 관련 기능, 회원가입,,
컨트롤러가 멤버 서비스 기능 통해 회원가입을 하고 , 데이터를 조회하게 하는 것
'컨트롤러가 멤버서비스를 의존한다. '라고 표현 한다.
프로젝트가 실행되고 스프링이 뜨면 스프링은 '스프링 컨테이너'에 자신이 사용할지도 모르는? 필요한 객체들을 담는다.
이 객체들을 스프링 Bean이라고 한다.
주로 Controller, Service,, 등이 아래에 해당 된다.
또한 어플리케이션이 진행되면서 해당 Bean들 사이의 상호 호출 등 연관성이 존재한다.
대표적인 예로는 Controller에서 Service를 호출하고 Service에서는 Repository를 호출하여 정보를 가져올 수 있다. 이렇게 bean사이에는 의존관계가 존재하고 이러한 의존관계를 주입해줘야한다.
스프링 빈 등록하는 방법
- 컴포넌트 스캔과 자동으로 의존관계 설정
@Controller , @Service, @Repository 어노테이션으로 해당 클래스가 스프링 빈임을 명시한다.
이어서, 다음과 같이 @Autowired를 통해 자동으로 의존 관계를 주입해준다.
(Bean에서 자동으로 찾아주세요~)
private final MemberService memberService;
@Autowired
public MemberController(MemberService memberService) {
this.memberService = memberService;
}
Q. 아무 패키지의 아무 클래스나 컴포넌트 스캔으로 Bean등록이 가능할까?
A. 아니다. 우리가 실행하는 HelloSpringApplication위에 @SpringBootApplication이라는 어노테이션을 사용하는데 해당 어노테이션이 사용된 메소드의 패키지와 하위 패키지들에 대해서만 Bean이 등록된다.
스프링 빈은 싱글톤으로 등록된다. 유일하게 하나만 등록된다는 뜻이다. 해당 컨테이너의 Bean을 다른 용도로 사용한다고 하더라도 하나의 Bean만 등록되고 등록된 내용을 바꿔가며 사용한다.
(물론, 여러 가지를 설정하는 방법도 있지만 대부분 하나만 사용한다.)
- 자바 코드로 직접 스프링 Bean 등록
SpringConfig 파일을 생성하고 @Configuration 어노테이션을 달아준다.
이어서 Bean으로 사용할 객체들에 대해서 @Bean 어노테이션을 사용한다.
아래에 MemberService를 반환하는 memberService 메소드를 만들고 @Bean으로 등록해 사용한다.
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository);
//아래 memberRepository 참조
}
@Bean
public MemberRepository memberRepository(){ //해당 인터페이셔 MemberRepository에 대하여
return new MemoryMemberRepository();// 어떤 구현체를 가져다 쓸건지
}
}
단, 컨트롤러는 컴포넌트 스캔으로 올라감. @Autowired를 사용해야한다.
DI엔 3가지 주입 방법이 있다. 위에서 사용한 방법이 생성자 주입.
- 필드 주입 : 중간에 바꿔줄 수가 없어서 애매한 방법.
@Autowired private MemberService memberService;
- setter 주입 : 변수를 생성하고 setter를 통해 생성
단점 - 누군가가 memberController를 쓰고 나면 public으로 열려있는 상태여야한다. 그러나, 스프링이 처음에 조립될때외에는 해당 코드가 변경, 수정될 이유가 없는데 public으로 사용하면 중간에 어플리케이션의 다른 부분에서 수정이 발생할 수 있기 때문에 빈약하다.
( 논리적으로 노출될 이유가 없는데 누군가가 바꿀 수 있음. )
- 생성자 주입 : 결론적으론 이게 좋다.
Q. 둘의 차이는 무엇일까?
일반적으로 정형화된 컨트롤러, 서비스, 리포지토리에는 컴포넌트 스캔이 유용하다. 다만, 정형화 되어있지 않거나 상황에 따라서 Interface를 구현하는 구현 클래스가 달라질 경우엔 스프링 빈으로 직접 등록해주는 방법이 유리하다.
예시는 다음과 같다.
public class SpringConfig {
@Bean
public MemberService memberService() {
return new MemberService(memberRepository);
//아래 memberRepository 참조
}
@Bean
public MemberRepository memberRepository(){ //해당 인터페이스 구현체를 DB로 변경
return new DbMemoryMemberRepository();
}
}
우리가 DB를 저장하지 않고 로컬저장소를 사용하는 방식으로 어플리케이션을 제작하다가 이제 DB로 바꿀때 다음과 같이 구현체 부분을 바꿔주기만 하면 된다.
@Autowired를 통해 DI를 할때에는 스프링 빈으로 등록된 객체에 한해서만 동작한다.
SpringConfig에 아무런 Bean도 등록하지 않았다면 @Autowired 어노테이션이 작동하지 않는다.
'BE > Spring - Inflearn 김영한' 카테고리의 다른 글
스프링 핵심 원리 - 기본편 1 (0) | 2023.03.16 |
---|---|
Spring 입문 인프런(무료강의) 김영한5 - DB접근 기술 (0) | 2023.03.13 |
Spring 입문 인프런(무료강의) 김영한3 (0) | 2023.03.10 |
Spring 입문 인프런(무료강의) 김영한2 (0) | 2023.03.10 |
Spring 입문 - 인프런(무료강의) (0) | 2023.01.10 |