[스프링 입문] 컴포넌트 스캔과 자동 의존관계 설정

김대준·2021년 12월 19일
0

spring

목록 보기
4/25
post-thumbnail

📌 스프링 빈(Bean)의 개념과 생성 원리

✔ 빈(Bean)

  • Spring IoC컨테이너가 관리하는 자바 객체를 빈(bean)이라고 부른다.
  • 우리가 new 연산자로 어떤 객체를 생성했을 때 그 객체는 빈이 아니다.
  • ApplicationContext.getBean()으로 얻어질 수 있는 객체는 빈이다.
  • 즉 Spring에서의 빈은 ApplicationContext가 알고있는 객체, 즉 ApplicationContext가 만들어서 그 안에 담고있는 객체를 의미한다.

✔ Spring IoC 컨테이너에 빈을 등록하는 방법

  • Component Scan과 자동 의존관계 설정
  • 자바 코드로 직접 스프링 빈 등록하기

📌 Component Scan과 자동 의존 관계 설정

  • 생성자에 @Autowired 가 있으면 스프링이 연관된 객체를 스프링 컨테이너에서 찾아서 넣어준다. 이렇게 객체 의존관계를 외부에서 넣어주는 것을 DI(Dependency Injection)

    • 생성자에 @Autowired를 사용하면 객체 생성 시점에 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입한다. 생성자가 1개만 있으면 @Autowired는 생략할 수 있다.

  • @Component : 스프링 빈으로 자동 등록. 해당 애노테이션을 포함하는 다른 애노테이션도 스프링 빈으로 자동 등록됨.

    • @Controller
    • @Service
    • @Repository

  • 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다.(유일하게 하나만 등록해서 공유한다.) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

스프링 컨테이너

@Component 은 스프링 컨테이너에 넣어준다면 그것들을 이어주는 것은 @Autowired이다.

package hello.hellospring.controller;

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

@Controller
public class MemberController {

    private  final MemberService memberService;

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

}

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<>();
    private  static long sequence = 0L;

    @Override
    public Member save(Member member) {
        member.setId(++sequence);
        store.put(member.getId(), member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }

    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member -> member.getName().equals(name))
                .findAny();
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());
    }

    public void clearStore(){
        store.clear();
    }
}


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

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

}

회원 서비스와 회원 리포지토리의 @Service, @Repository, @Autowired 애노테이션을 제거하고
진행한다.

참고: DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있다. 의존관계가 실행중에
동적으로 변하는 경우는 거의 없으므로 생성자 주입을 권장한다

주의: @Autowired 를 통한 DI는 helloConroller , memberService 등과 같이 스프링이 관리하는
객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.

profile
kureungkureung

0개의 댓글