yyndevv 2023. 2. 25. 00:36

* 인프런 김영한님의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의를 듣고 작성한 내용입니다.

  (강의 링크)

 

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

  • 회원 서비스와 회원 리포지토리의 @Service, @Repository, @Autowired 애노테이션을 제거하고 진행
  • 하나하나 직접 스프링에 등록하는 방법

 

기존 컴포넌트 스캔 방식의 코드에서 @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());
        //MemberService 인자로 아래 memberRepository 엮어주어야
    }
    // 스프링 뜰 때 @Configuration 읽고 이건 스프링 빈에 등록하라는 뜻이네 하고 로직 호출해서 스프링 빈에 등록

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }

}

 

실행하면 memberSerivice memeberRepository 둘 다 스프링 빈에 등록

→ 스프링 빈에 등록되어있는 memberRepository memberSevice에 넣어주게 되고 아래와 그림과 같은 의존관계 완성

참고: @Controller는 스프링이 관리하는 것이기 때문에 컴포넌트 스캔 방식으로 작성해야 함

 

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());
        //MemberService 인자로 아래 memberRepository 엮어주어야
    }
    // 스프링 뜰 때 @Configuration 읽고 이건 스프링 빈에 등록하라는 뜻이네 하고 로직 호출해서 스프링 빈에 등록

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }

}

자바 코드로 직접 스프링 빈 등록한 방식으로 정상 실행 확인


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

  • 컴포넌트 스캔과 자동 의존관계 설정: 더 편리하고 자주 사용
  • 자바 코드로 직접 스프링 빈 등록하기
  • 참고: XML로 설정하는 방식도 있지만 최근에는 잘 사용하지 않으므로 생략

 

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

 

상황에 따라 구현 클래스를 변경?

초반 설정 내용: 데이터 저장소 선정되지 않아서 우선 인터페이스 설계 후 구현체로 MemoryMemberRepository 만들었으며 추후 데이터 저장소 바꾸어야 함.

→ MemorMemberRepository를 데이터 베이스에 실제로 연결하는 리포지포리로 바꿀 때 기존 코드나 나머지 내용에 일절 손대지 않고 나중에 다른 것으로 바꿔치기 할 예정. 기존 운영중인 코드 하나도 손대지 않고 바꾸는 방법!

나중에 이 부분만 DB 리포지토리로 바꾸면 된다

 

@Autowired 통한 DI

  • helloController , memberService 등과 같이 스프링이 관리하는 객체에서만 동작한다.
  • 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

DI 방법 3가지

  • 생성자 주입: 의존관계가 실행중에 동적으로 변하는 경우는 거의 없으므로(대부분 바꿔서 서버 다시 동작하게 함) 생성자 주입을 권장한다.
  • 필드 주입
  • setter 주입

생성자 주입

  • 요즘 권장하는 스타일
  • MemberController 실행 시 생성자 통해서 memberService가 컨트롤러로 들어옴
  • 처음에 에플리케이션 조립되는 순간에 생성자 들어오고 나면 끝남 → 즉, 생성 시점에만 넣고 변경 못하도록 막아버릴 수 있음

필드 주입

  • 별로 좋지 않다. 중간에 바꿀 수 있는 방법 존재 X

Setter 주입

  • 개발에서는 최대한 호출하지 않아야 할 메서드 호출하지 않도록 해야 하므로 권장하지 않는 방식
  • 문제점: 누군가가 memberController 호출했을 때 setMemberService public으로 열려 있어야 함. setMemberService 한 번 세팅하고 나면 바꿀 이유 없음에도 불구하고 public하게 노출이 됨. 예) memberService.setMemberRepositoy(); 누구나 호출 가능