[SpringBoot/Java/04. 스프링 빈 등록 및 의존관계(DI) 설정]

안지은·2023년 2월 1일
0

💡 스프링 빈을 등록하고, 의존관계 설정하기

스프링의 DI(Dependencies Injection)를 사용하면 기존 코드를 전혀 손대지 않고, 설정만으로 구현 클래스를 변경할 수 있다.

1. 컴포넌트 스캔 방법

컨트롤러는 서비스를 통해 회원가입 및 데이터 조회를 할 수 있어야 한다. 이때 컨트롤러가 서비스를 의존한다고 표현한다. 회원 컨트롤러가 회원 서비스와 회원 리포지토리를 사용할 수 있도록 의존관계를 준비하자.

MemberController.java

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 {

    @Autowired  //스프링 빈에 등록된 memberService를 가져와 연결시킴.
    //MemberController 객체가 생성될 때 아래 생성자가 호출됨.
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }

    private final MemberService memberService;
    
}

@Autowired를 통해 컨트롤러와 서비스를 연결시켰다.

@Controller가 있으면 스프링이 MemberController 객체를 생성하여 스프링 컨테이너에 넣어 관리한다. 이를 스프링 컨테이너에서 스프링 빈이 관리된다고 표현한다. 서비스와 리포지토리도 스프링이 스프링 컨테이너에 등록하여 관리할 수 있도록 아래와 같이 애노테이션을 작성해준다. 이런식으로 스프링 빈을 등록하는 방법을 컴포넌트 스캔이라고 한다.

MemberService.java에서 @Autowired를 통해 서비스와 리포지토리를 연결시키자.

//회원 서비스를 만드려면 회원 리포지토리가 필요하다.
    private final MemberRepository memberRepository;

    @Autowired //memberRepository를 주입함. (Dependency Injection)
    //스프링 컨테이너에 MemberService가 등록될 때 아래 생성자 호출.
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

컨트롤러를 통해서 외부 요청을 받고, 서비스에서 비즈니스 로직을 만들고, 리포지토리에서 데이터를 저장하는 패턴이다.

@Controller이나 @Service, @Repository 애노테이션이 아닌 @Component 애노테이션이 있어도 스프링 빈으로 자동 등록될 수 있다. 하지만 아무 패키지의 클래스에 @Component를 붙인다고 해서 스프링 빈으로 등록될 수 있을까?

아니다. 웹이 시작되는 HelloSpringApplication이 포함된 최상위 패키지 안의 하위 패키지에 존재하는 애들을 스프링이 스프링 빈으로 등록한다. 이 최상위 패키지와 동일하거나 하위 패키지가 아닌 애들은 컴포넌트로 등록하지 않는다.

참고 : 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다. 여기서 싱글톤이란 유일하게 하나만 등록하여 공유하는 것이다. HelloController이란 컨트롤러를 컨테이너에 딱 하나만 등록해 공유하여 쓰는 것처럼 말이다. 따라서 같은 스프링 빈이면 모두 같은 인스턴스이다.

주의 : 스프링 빈으로 등록을 해야 @Autowired가 동작한다. 또한 스프링 빈으로 등록하지 않고 자신이 직접 new를 통해 memberService와 같은 객체에서는 @Autowired가 적용되지 않는다. 스프링이 관리하는 객체, 즉 컨테이너에 올라가는 것들만 적용된다.

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

이번에는 자바 코드로 직접 스프링 빈을 등록해보자. 회원 서비스와 회원 리포지토리의 @Service, @Repository, @Autowired 애노테이션을 제거하고 진행한다. (컨트롤러는 그대로 놔둔다.)

SpringConfig.java

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

서비스와 리포지토리를 스프링 빈으로 등록함과 동시에 둘을 연결해준다.

참고

Dependency Injection(DI)에는 필드 주입, setter 주입, 생성자 주입이 있다. 필자는 위에서 진행한 생성자 주입 방법을 사용하는 것을 권장한다.

실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다. 그리고 정형화되지 않거나, 상황에 따라 구현 클래스(ex) MemoryMemberRepository)를 변경해야 하면 자바 코드를 통해 스프링 빈으로 등록한다.

profile
공부 기록용

0개의 댓글