티스토리 뷰

💡컨포넌트 스캔과 자동 의존관계 설정

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

 

MemberController가 MemberService를 통해 회원가입하고, 데이터 조회할 수 있어야 하는데, 이것을 MemberController가 MemberService를 의존하는 '의존관계'에 있다고 한다.

💻MemberController 생성

package hello.hellospring.controller;

import hello.hellospring.service.MemberService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

//controller 통해서 외부 요청 받고, 서비스에서 비즈니스 로직 만들고, 리포지토리에 데이터 저장 -> 정형화된 패턴
@Controller
public class MemberController { //얘도 spring 컨테이너가 관리를 하게 됨

    //private final MemberService memberService = new MemberService();
    //new 해서 하면 memberCotroller말고 다른 controller들디 memberService가져다 쓸 수 있음
    //여러개의 인스턴스 생성할 필요 없이 하나 생성해놓고 공용으로 쓰면 됨 -> spring 컨테이너에 하나 등록하고 쓰기 (하나만 등록이됨)
    private final MemberService memberService;

    @Autowired //그런데 생성자에 AutoWired라고 되어 있으면 이 멤버 서비스를 스프링이
    // 스프링 컨테이너에 있는 멤버 서비스를 가져다가 연결을 딱 시켜줍니다
    // 생성자에서 이렇게 쓰면 멤버 컨트롤러가 생성이 될 때 스프링 빈에 등록되어 있는 멤버 서비스를 객체를 가져다가 넣어줌 = dependency Injection
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }


}

 

@Controller를 통해 컨트롤러가 스프링 빈(초록색 콩 모양)에 등록된다.

 

@Autowired는

생성자에 Autowired라고 되어 있으면 스프링이 스프링 컨테이너에 있는 멤버 서비스를 가져다가 연결을 시켜준다.
생성자에서 이렇게 쓰면 멤버 컨트롤러가 생성이 될 때 스프링 빈에 등록되어 있는 멤버 서비스를 객체를 가져다가 넣어준다. = dependency Injection

but, 위 코드를 바로 실행하면 오류가 난다.

MemberController가 MemberService를 통해 회원가입하고 데이터 조회하기 위해 @Autowired를 통해 스프링 컨테이너에 있는 MemberService를 가져와야 하는데, 현재 스프링 컨테이너에 MemberService가 없다.

 

💻스프링 컨테이너에 스프링 빈 연결

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class MemberService {

    // 저장소
    //private final MemberRepository memberRepository = new MemoryMemberRepository();

    private final MemberRepository memberRepository;

    @Autowired //MemberService 등록하면서 이 생성자도 호출함
    //그런데 그때 이 오토 와이어드가 있으면 아 너는 멤버 리포지토리가 필요하구나고 해서
    //스프링 컨테이너에는 멤버 리포지토리를 넣어줌
    //memoryMemberRepository가 구현체로 있어서 이 memoryMemberRepository를 서비스에 주입해줌
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

@Service를 통해 MemberService를 스프링 컨테이너에 넣어 스프링 빈에 등록해주었다.

이제 MemberService는 MemberController와 서로 연결되는 의존관계이다.

 

MemberService가 MemberRepository의 메서드인 save, findById, findByName을 사용해야 하므로, 여기도 @Autowired 해주었다.

이제 @Autowired를 통해 스프링 컨테이너에 있는 MemberRepository를 가져다 연결시켜주면 된다.

그러나 현재 스프링 컨테이너에 MemberRepository가 없으므로 아까처럼 이도 스프링 빈에 등록해줘야 한다.

package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.stereotype.Repository;

import java.util.*;

@Repository
public class MemoryMemberRepository implements MemberRepository{

 @Repository 코드를 추가하여 MemberRepository의 구현체인 MemoryMemberRepository를 스프링 빈으로 등록시켜주었다.

 

이제 memberService 와 memberRepository 가 스프링 컨테이너에 스프링 빈으로 등록되었고, 의존관계도 확인할 수 있다.

 

💻 추가 설명

지금까지 한 건 컴포넌트 스캔과 자동 의존관계 설정 방법이었다.

 

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

💻 자바 코드로 스프링 빈 연결

먼저, MemberService와 MemoryMemberRepository의 @Service, @Repository, @Autowired 를 지워줘야 한다.

단, MemberController는 그대로 냅둔다.

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

//@Service
public class MemberService {

    // 저장소
    //private final MemberRepository memberRepository = new MemoryMemberRepository();

    private final MemberRepository memberRepository;

    //@Autowired //MemberService 등록하면서 이 생성자도 호출함
    //그런데 그때 이 오토 와이어드가 있으면 아 너는 멤버 리포지토리가 필요하구나고 해서
    //스프링 컨테이너에는 멤버 리포지토리를 넣어줌
    //memoryMemberRepository가 구현체로 있어서 이 memoryMemberRepository를 서비스에 주입해줌
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
package hello.hellospring.repository;

import hello.hellospring.domain.Member;
import org.springframework.stereotype.Repository;

import java.util.*;

//@Repository
public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();

//주석 처리 해줌

 

그리고 이제 SpringConfig라는 새로운 클래스 파일을 생성해야 프로젝트를 실행할 때 오류가 발생하지 않는다.

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 사용하도록 메서드 호출
    }

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

 

이제 스프링 컨테이너에 스프링 빈으로 등록이 되었고, 서로 의존관계를 가지게 되었다.

 

💻주의 및 참고

여기서는 향후 메모리 리포지토리를 다른 리포지토리로 변경할 예정이므로, 컴포넌트 스캔 방식 대신에 자바 코드로 스프링 빈을 설정하였다.

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

자바 코드로 스프링 빈을 설정하면 나중에  return new DbMemberRepository(); 이렇게만 바꿔주면 된다.

    public static void main(String[] args) {
        MemberService memberService = new MemberService(); //동작하지 않음
    } 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/08   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
글 보관함