스프링 빈과 의존관계

박민서·2023년 5월 2일
0

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

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에 의해 스프링이 주입해준다.

MemberService는 순수한 클래스다 스프링이 얘를 알 방법이 없다. 그러면 @Service를 넣어주면된다 그리고 리포지토리 구현체로 가서 @Repository를 해준다. 컨트롤러랑 서비스랑 연결을 시켜줘야됨 @Autowired 이게바로 의존관계를 주입시켜 주는것 memorymemberrepository가 구현체로 있는 것을 딱 서비스에 주입을 해줌

스프링 빈을 등록하는 2가지 방법 컴포넌트 스캔과 자동 의존관계 설정

  • 컴포넌트 스캔 : @Service @Repository @Autowired 이런 방식 스프링이 딱 올라올 때 어노테이션이 있으면 컴포넌트에 등록이 됨
  • 자바코드로 직접 스프링 빈 등록하기

아무 때나 @Component가 있어도 될까? 이거는 기본은 안된다. 우리가 실행시키는 HelloSpringApplication의 패키지를 포함해서 하위들은 자동으로 스프링이 뒤져서 빈에 등록됨

싱클톤 : 유일하게 하나만 등록함 hellocontroller 은 hellocontroller 하나만 memberservice는 memberservice하나만 등록을 하고 공유한다.

회원 서비스 스프링 빈 등록

@Service	// 스프링이 실행될 때, 스프링 컨테이너가 서비스 객체를 만들고 스프링 빈으로 등록한다.
public class MemberService {
 private final MemberRepository memberRepository;
 @Autowired
 public MemberService(MemberRepository memberRepository) {
 this.memberRepository = memberRepository;
 }
}
  • 생성자가 하나라면 @Autowired 생략 가능
  • 컨트롤러는 어쩔 수 없이 스프링이 관리하기 때문에 자바 코드로 직접 스프링 빈 등록할 순 없음

회원 리포지토리 스프링 빈 등록

@Repository // 스프링이 실행될 되면 스프링 컨테이너가 서비스 객체를 만들고 스프링 빈으로 등록한다.
public class MemoryMemberRepository implements MemberRepository {}

스프링 빈 등록 이미지

  • memberService 와 memberRepository 가 스프링 컨테이너에 스프링 빈으로 등록되었다

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

자바 코드로 직접 스프링 빈 등록하기

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();
 }
}

DI에는 3가지 방법이 있는데 하나가 생성자 주입 두번째 필드 주입(별로 안좋음) 마지막으로 SETTER 주입이 있다 SETTER를 만들어주고 @Autowired 달아줌 이거에 단점은 누군가가 멤버 컨트롤을 호출하면 퍼블릭으로 노출이되어야 함 요즘 권장하는 것은 생성자 주입

public MemberService(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}

  • 이렇게 생성자를 통해서 들어오는 것을 생성자 주입이라 함

실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다.
정형화된 컨트롤러는 일반적으로 우리가 작성하는 컨트롤러 서비스 리포지토리
그리고 정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다 -> 중요 상황에 따라 구현 클래스를 변경해야 한다!

profile
ㅎㅇㅌ

0개의 댓글