본문 바로가기
백엔드 공부/스프링 입문

스프링 빈과 의존관계

by CSEGR 2024. 3. 6.
728x90

(인프런) 김영한 님의 스프링입문 - 코드로 배우는 스프링부트,웹 MVC, DB접근기술  강의를 보고 리뷰한 글입니다. 

"스프링 빈을 등록하는 두 가지 방법"

  • 컴포넌트 스캔과 자동 의존 관계 설정 
  • 자바 코드로 직접 스프링 빈 등록하기 
컴포넌트 스캔과 자동 의존관계 설정 

= @AutoWired 사용하기 

 

MemberController -> MemberService를 통해서 회원가입 및 회원 조회가 가능하게 해야함. 

➔MemberController와 MemberService는 서로 의존관계에 있다. = MemberController가 MemberSerive를 의존한다. 

 

@Controller를 선언해놓은 경우, 이 MemberController 객체를 생성해서 Spring에 넣어두고 Spring이 관리. 

➔스프링 컨테이너에서 스프링 빈이 관리된다고 표현.

Controller 에노테이션이 있으면, 스프링이 뜰 때 생성을 해서 관리 및 사용함.

@AutoWired는 스프링 컨테이너에서 MemberService가져옴. 즉, 스프링이 전달받은 MemberService를 컨테이너에서 

관리하는 MemberService를 가져다가 연결시켜줌.  

 

 

@Controller -> 컨트롤로를 통해서 외부로 요청을 받고,

@Controller
public class MemberController{}

@Service -> 서비스에서 비즈니스 로직을 만들고, 

@Service
public class MemberService {}

@Repository(회원 레포지토리 스프링 빈 등록) -> 레포지토리에서 데이터를 저장하고 

@Repository
public class MemoryMemberRepository implements MemberRepository{}

➜정형화 되어 있는 패턴임. 

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

Controller와 Service는 @AutoWired를 이용하여 연결시켜준다. 생성자에서 이렇게 쓰면 멤버 컨트롤러가 생성이 될 때 스프링 빈에 등록되어 있는 멤버 서비스 객체를 가져다가 넣어줌. 

 

➔➔Dependency Injection = 의존관계를 주입해주는 개념 

@Controller
public class MemberController {

    //스프링 컨테이너에 등록해놓고 하나로 공유 자원.
    private final MemberService memberService;

    //@Autowired를 쓰면 스프링이 전달받은 MemberService를
    //스프링 컨테이너에 있는 MemberService를 가져다가 연결을 시켜줌.
    @Autowired
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

 

@Service
public class MemberService {
    private final MemberRepository memberRepository;

    //MemberRepository가 필요한 걸 인지하고 컨테이너에 있는 멤버레포지토리를 넣어줌.
    @Autowired
    public MemberService(MemberRepository memberRepository){
        this.memberRepository = memberRepository;
    }
 }

 

@Component 가 있으면 자동으로 스프링 빈이 등록된다. 

@Component를 포함하는 다음 에노테이션도 스프링 빈도 자동 등록된다. 

  • @Controller
  • @Service 
  • @Repository

 

즉, Component와 관련된 애노테이션이 있으면 스프링 객체를 하나씩 생성해서 스프링 컨테이너에 등록을 함. 

@AutoWired 은 스프링 객체간의 연결 관계를 연결해주는 기능을 함. 

연결이 되면 MemberController가 MemberService를 쓸 수 있게 해주고, MemberService가 MemberRepository를 쓸 수 있게됨 .

HelloSpringApplication을 통해 실행시키는데

package hello.hellospring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloSpringApplication {

	public static void main(String[] args) {
		SpringApplication.run(HelloSpringApplication.class, args);
	}

}

hello.hellospring 패키지에 있는 하위들은 자동으로 spring이 애노테이션을 찾아 스프링 빈을 등록시켜줌.  

즉, 컴포넌트 스캔의 대상이 되기 위해선 hello.hellospring 패키지 하위에 있어야함.  

 

 

+) 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글 톤으로 등록한다. (유일하게 하나만 등록시킨 다는 의미)

따라서 같은 스트링 빈이면 모두 같은 인스턴스이다. 

 

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

 

먼저 이전에 컴포넌트 스캔을 위해 추가해둔 회원서비스와 회원 레포지토리의 @Service, @Repository, @AutoWired의 에노테이션을 제거하고 진행한다. 

//hello/hellospring/service/SpringConfig.java

package hello.hellospring.service;

import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {

	//MemberService를 스프링 빈에 등록함. 
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }
    
    //MemberRepository를 스프링 빈에 등록함. 
    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
        //memberRepository는 interface, 즉 구현체는 MemoryMemberRepository.
    }
}

 스프링빈에 등록되어있는 MemberRepository를 MemberService에 넣어줌. 

 

● DI(= Dependency Injection)에는 필드 주입, setter 주입, 생성자 주입 이렇게 세 가지 방식이 있다.

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

 

  • 생성자 주입 👍권장 
@Controller
public class MemberController {
    private final MemberService memberService;

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

-> 생성자를 통해서 memberService가 MemberController에 주입이 되고 있음. 

 

  • 필드 주입  // 비추하는 방법 
@Controller
public class MemberController {
    @Autowired private final MemberService memberService;
}

 

  • setter 주입 
@Controller
public class MemberController {
    private MemberService memberService;

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

 

728x90