Computer Engineering/Java & Spring

[spring] 스프링 빈과 의존관계2- 자바 코드로 직접 스프링 빈 등록

soohey 2022. 6. 26. 22:23
 

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 인프런 | 학습 페이지

지식을 나누면 반드시 나에게 돌아옵니다. 인프런을 통해 나의 지식에 가치를 부여하세요....

www.inflearn.com

 

스프링 빈을 등록하는 2가지 방법 중

자바 코드로 직접 스프링 빈을 등록하는 방법을 소개합니다.

 

컴포넌트 스캔으로 스프링 빈 자동등록하는 방법은 

 

[spring] 스프링 빈과 의존관계1 - 컴포넌트 스캔으로 자동 의존관계 설정

김영한님의 인프런 스프링 강의 리뷰입니다. XD 스프링 빈을 등록하고 의존관계 설정하기 회원 컨트롤러가 회원서비스와 회원 리포지토리를 사용할 수 있도록 의존관계를 준비하자. "회원 컨트

soohey.tistory.com

 

코드로 스프링 빈을 등록하면 어노테이션을 사용하지 않고 설정 파일을 통해서 직접 스프링빈으로 등록할 수 있습니다.

절차는 아래와 같습니다.

 

코드 작성 절차

  1. 스프링 빈으로 설정되도록 코드를 작성한다.
  2. 두 리포지토리(MemberRepository, MemoryMemberRepository)를 스프링 빈으로 설정한다.(@Configuration, @Bean을 사용함)
  3. 스프링 빈에 등록된 MemberRepository를 MemberService에 넣어준다.

 

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

위 코드는 이런 의미를 가집니다.

  • MemberService는 MemberRepository를 사용하도록 설정합니다.
  • MemberRepository를 MemoryMemberRepository를 사용하도록 설정합니다.

 

컨트롤러는 스프링이 관리하기에 보통 어노테이션 설정으로 등록됩니다. (@Autowired 사용하기)

 

위처럼 코드를 작성했다면 아래와 같이 스프링 빈 등록 이미지가 완성됩니다.

<스프링 컨테이너>
helloController -> memberService -> memberRepository

 

 

참고사항

 

실무에서는 자바코드로 스프링 빈을 등록하는 방식을 많이 사용한다.

 

DI에는 필드 주입, setter 주입, 생성자 주입으로 3가지 방법이 존재한다.

의존관계가 실행중에 동적으로 변하는 경우는 거의 없기 때문에 생성자 주입을 권장한다.

(진짜 바뀌어야 할 경우에는 config파일을 수정한 이후 서버에 다시 올리는 방법을 사용합니다.)

  • 생성자 주입 : 생성자를 통해 멤버 서비스를 컨트롤러에서 사용한다.
  • 필드 주입 : 생성자를 빼고 필드에 @Autowired를 사용하는 경우. 중간에 변경하기 어려워 좋지 않은 방법이다.
  • setter 주입 : set을 붙인 후 @Autowired를 달아준다. 생성은 생성대로, set은 set대로 분리하여 작성한다. 단점은 누군가가 MemberController로 호출했을 때 public으로 작성해야한다. (이 경우 모든 개발자가 사용할 수 있도록 노출될 수 있음. 최대한 호출되면 안되는 메소드의 경우 노출하지 않는 것이 좋다.) 또한 한번 셋팅하고 난후 바꿀일이 없기 때문에 단점일 수 있다.

실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용한다.

그리고 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록해야 한다. (중요!)

 

설정파일을 통해 스프링빈으로 등록하면 나중에 리포지토리를 변경할 때 용이하다.

가상의 시나리오를 작성할 때, 아직 데이터 저장소가 선정되지 않아서(나중에 변경해야할 경우)

MemberRepository(인터페이스)를 만들고 MemoryMemberRepository(구현체)를 만들어 우선 인터페이스로 구현 클래스를 변경할 수 있도록 설계한다.

이때 다른 부분을 건드리지 않고 메모리를 변경할 수 있는 방법이 존재한다.

MemoryRepository를 실제 DB로 연결하는 리포지토리로 바꾸면 되는데, 기존 코드를 손대지 않고 바꿀 수 있다.

MemoryMemberRepository를 DbMemberRepository()로 변경하면 코드 한줄로 변경할 수 있다!

 @Bean
    public MemberRepository memberRepository(){
    	//실제 DbRepository로 변경
        //return new MemoryMemberRepository();
        return new DbMemberRepository();
    }

 

주의 : @Autowired를 통한 DI는 스프링이 관리하는 객체에서만 동작한다.

스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

ex) MemberService가 스프링 빈으로 관리되고 있지 않을 경우, @Autowired로 의존 관계 설정이 불가하다.

서비스를 스프링 빈(@Bean)으로 등록해야 @Autowired를 사용할 수 있다.