본문 바로가기

Spring

Spring- 컴포넌트 스캔과 자동 의존관계 설정

스프링 빈


스프링 빈은 스프링 컨테이너에 의해서 관리되는 자바 객체를 의미.

 

스프링 빈 등록 방식


component scan

 자바 클래스 위에 @Component 어노테이션을 붙이면 해당 클래스는 스프링이 자동으로 스프링 빈으로 등록해준다.

 @Component를 상속받는 어노테이션의 종류

   -@Controller

   스프링 MVC 컨트롤러로 인식된다. (스프링에 다양한 정보를 던줌)

   -@Repository

   스프링 데이터 접근 계층으로 인식된다. (다양한 기능적인 로직 구현)

   -@Service

   스프링 비즈니스 계층으로 인식된다. (서비스 계층에서 레포지토리에서 만들어진 기능을 활용해 비즈니스적으로 구현)

   -@Configuration

   스프링 설정 정보로 인식된다.

   

 

Defendency injection (의존 관계 설정)


@Autowired

  클래스가 스프링 빈으로 연결되어 스프링에서 생성자가 실행될때, 인자의 값이 이미 스프링 내부에 있는 값으로 넣어짐.

현재 구현 정보

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);  //member에 id 부여
        store.put(member.getId(), member ); //Map에 id와 member 인스턴스 저장
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id));  //id가 존재시 해당 멤버 반환. 없다면 null 반환
        //Optional.ofNullable()은 get(id)의 반환값이 null일때를 대비해서 감싸줌
    }

    @Override
    public Optional<Member> findByName(String name) {
        return store.values().stream()
                .filter(member->member.getName().equals(name))  //member의 getName() 반환값이 name과 같은 경우에만 필터링
                .findAny();
    }

    @Override
    public List<Member> findAll() {
        return new ArrayList<>(store.values());  //member들이 반환
    }

    public void clearStore(){
        store.clear(); //저장소 비우는 코드
    }
}
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 {  //MemoryMemberRepository 클래스의 기능을 비즈니스 로직으로 구현
    //MemberRepository는 인터페이스. MemoryMemberRepository는 MemberRepository 상속받는 클래스
    private final MemberRepository memberRepository;

    @Autowired  //@Autowired: defendency injection 해줌
    //스프링에서 MemberService가 인스턴스 넘어가서 생성자가 실행될 때
    // 스프링 내부에 있는 memberRepository를 인자로 넣어줌.
    // 따라서 memberRepository는 빈으로 등록되어있어야함
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    /*
         회원 가입
         */
    public Long join(Member member){
        //같은 이름이 있는 중복 회원x
        validateDuplicateMember(member);  //중복 회원 검증
        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMember(Member member) {
        Optional<Member> result = memberRepository.findByName(member.getName());
        result.ifPresent(m -> {  //ifPresent는 Optional의 메소드. 값이 널이 아니라면 실행
            throw new IllegalStateException("이미 존재하는 회원입니다.");
        });
    }

    /*
    * 전체 회원 조회
    */
    public List<Member> findMembers(){
        return memberRepository.findAll();
    }

    public Optional<Member> findOne(Long memberId){
        return memberRepository.findById(memberId);
    }
}
package hello.hellospring.controller;

import hello.hellospring.domain.Member;
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  //defendency injection 해줌
    //MemberController의 생성자가 실행시 스프링 내부에 있는 memberService를
    //자동으로 인자로서 넣어준다.
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

 (세번째 코드 블록에서)MemberController의 생성자가 실행될 때 인자로 MemberService memberService가 들어와야 하는데, 이게 이미 스프링 내부에 있는 값이 들어온다는 것임. 따라서 MemberService도 스프링 빈으로 선언이 되어 있어야한다.(스프링 내부에 존재하기 위해서)