[spring 입문] 스프링 빈과 의존관계

김영한 선생님 인강들으면서 정리중,,


멤버 컨트롤러가 멤버 서비스 통해서 회원가입, 조회 가능
-> 멤버 컨트롤러가 멤버 서비스에 의존한다 라고 이야기

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


Controller 폴더 내부에 MemberController 생성
어노테이션 @Controller 있으면 스프링이 관리한다.

스프링 컨테이너에서 빈이 생성된다고 이야기.
스프링 컨테이너가 관리

여러 컨트롤러가 가져다 쓸 수 있다.(ex 주문, )
하나만 생성하고 공용으로 쓴다. -> 스프링 컨테이너에 등록하고 (스프링 컨테이너에 하나만등록됨) 부가적인 여러가지 효과를 볼 수 있다.
@Autowired를 사용하면 스프링컨테이너에서 가져온다.

@Service 를 MemberService에 넣어주고
@Repository를 MemoryMemberRepository에 넣어주기

컨트롤러, 레포지토리, 서비스가 정형화된 패턴
스프링이 뜰 때 컨트롤러 리포지토리 가져온다.

-> 의존관계 주입 (DI)

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

두 가지 모두 알아야 함.
@Component 애노테이션이 있으면 스프링 빈으로 자동 등록된다.

@Controller @Service @Repository 모두 안에 @Component을 가지고 있음

@Autowired는 연관관계 해주는역할

스프링은 스프링 컨테이너에 스프링 빈 등록 시, 기본으로 싱글톤 등록함.
즉, 같은 스프링 빈이면 모두 같은 인스턴스. (설정으로 바꿀 순 있음. 지금은X )

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;
    @Autowired
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }


    // 회원가입
    public Long join(Member member) {
        validateDuplicateMember(member);    // 같은 이름 X 중복회원검증

        memberRepository.save(member);
        return member.getId();
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 존재하는 회원입니다.");
                });
    }
    //전체 회원조회
    public List<Member> findMember() {
        return memberRepository.findAll();
    }

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

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

}

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


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

@Configuration @Bean 이용해서 직접 등록

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

각각 장단점 있음
과거는 xml 문서로 설정했음
DI에는 필드주입, setter 주입, 생성자 주입 세가지가 있음

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

이게 생성자 주입

필드주입은
@Authowired private MemberService memberService;
(별로 안좋음, 중간에 바꿀 수 있는 방법이 없기 때문 )

setter 주입은 setter 통해서 생성 , 호출, setter Injection 방식
단점은 누군가가 컨트롤러 호출했을 때 public으로 열려있어야함. 중간에 바꾸면 문제생기고 노출이 되어있는 단점 있음

요즘 권장 스타일은 '생성자 이용 주입 '
어플리케이션 조립 시점에 들어오고 끝난다.
(의존관계가 실행중에 (runtime) 동적으로 변하는 경우는 거의 없으므로)

주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드는 컴포넌트 스캔을 사용
정형화 되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다.
-> MemberRepository 에 데이터 저장소 선정 안됐다는 가정이 있음
나중에 다른 repository로 바꾼다.
기존 운영 코드 손대지 않고 바꿀 수 있는 방법이 있음.
그래서 이거 쓰는 것임.

컴포넌트 스캔하면 여러가지 바꿔야하지만,
직접 코드구현으로 하면 설정파일만 바꿔서
기존 Memberservice나 나머지 코드 일절 손대는 것 없이 바꿔치기 할 수 있다.

좋은 웹페이지 즐겨찾기