본문 바로가기

개발일지/Spring

[Spring] 스프링 입문 - 스프링 빈과 의존 관계

회원 컨트롤러가 회원 서비스, 리포지토리를 사용할 수 있게 의존관계를 준비한다

 

Controller 어노테이션

 

스프링 컨테이너가 창에 뜨면, 스프링 컨테이너 라는 이 생긴다

Controller 어노테이션이 있으면 MemberController 객체를 생겨서 통에 넣어두고, 스프링이 관리한다

 

new 방식으로 객체를 생성하지 말고,

컨테이너에 하나만 등록해서 그 등록한 것을 사용하자!

 

Autowired

  • 스프링 컨테이너에서 memberService를 가져오는데, 생성자에 접근

 

순수한 자바 코드였던 MemberService에 Service라는 어노테이션을 초기에 선언

→ 스프링이 Service라는 어노테이션을 보고, 스프링 컨테이너에 MemberService를 등록

 

Controller, Repository도 마찬가지!

 

 

 

스프링이 뜰 때, 컨트롤러, 서비스, 리포지토리를 모두 가져온다

스프링은 서비스 어노테이션을 보고, Autowired 를 통해 생성자를 호출한다

 

 

이 때, Autowired 어노테이션이 있으면?

컨테이너에 등록된 MemberRepository를 주입한다!

 

 

 

지금까지 한 것이 컴포넌트 스캔 방식!

Controller, Service, Repository 어노테이션에 들어가보면 @Component 어노테이션이 선언되어 있다

 

컴포넌트 어노테이션이 있으면 스프링 빈으로 자동 등록된다

 

 

어디부터 적용이 되는 걸까?

 

HelloSpringApplication 코드가 있는 패키지의 하위패키지, 즉 스프링은 hello.hellospring의 하위 패키지를 탐색한다

 

 

스프링 빈은 싱글톤으로 등록된다

스프링이 스프링 컨테이너에 스프링 빈을 등록할 때,

기본적으로는 싱글톤으로 등록된다

 

싱글톤 ? 유일하게 하나만 등록해서 공유

특수한 경우가 아니면 싱글톤으로 등록하자

 

 

 

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

 

SpringConfig 파일을 하나 생성하고,

스프링이 뜨면 @Configuration을 통해 들어온다

이 때, @Bean 어노테이션이 있으면 스프링 빈에 등록을 한다 !

 

 

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}
  1. memberService와 memberRepository를 둘 다 빈에 등록 한다
  2. 빈에 등록된 memberRepository를 memberService에 넣어준다

 

 

DI의 3가지 방법

  • 생성자 주입 : 의존관계가 실행중에 동적으로 변하는 경우가 거의 없으므로, 생성자 주입을 주로 권장
@Controller
public class MemberController {
    private final MemberService memberService;

    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

 

  • 필드 주입 : 중간에 바꿀 수 있는 방법이 없어서 권장 X
@Autowired private MemberService memberService;

 

  • setter 주입 : public하게 노출이 되어서 잘못 바꾸면 문제가 생길 수 있다
private MemberService memberService;
    
    @Autowired
    public void setMemberService(MemberService memberService) {
        this.memberService = memberService;
    }

 

컴포넌트 스캔 VS 자바 코드로 직접 등록

실무에서 정형화 된 컨트롤러, 서비스, 리포지토리 → 컴포넌트 스캔

정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 할 때 → 자바 코드로 직접 스프링 빈 등록

💡 Spring Bean으로 등록되지 않은 서비스에 Autowired 어노테이션을 사용하면 어떻게 될까?

동작하지 않는다
스프링 빈으로 등록되고 스프링이 관리를 해야 Autowired가 동작한다

 

 

 

 

@참고자료

[인프런] 김영한 - 스프링 입문 강의 (무료)