8. 의존성 주입(dependency injection) (Spring)

2023. 4. 3. 15:40·Spring
728x90

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Spring 프레임워크는 3가지 핵심 프로그래밍 모델을 지원하고 있는데, 그 중 하나가 의존성 주입(Dependency Injection, DI) 입니다.

 

 

 

 

 

DI 란 무엇인가

 

DI는 Dependency Injection의 줄임말로, 다양한 우리 말 번역이 있지만, 이 글에서는 의존성 주입이라고 하겠습니다.

 

DI란 외부에서 두 객체 간의 관계를 결정해주는 디자인 패턴으로, 인터페이스를 사이에 둬서 클래스 레벨에서는 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 동적으로 주입하여 유연성을 확보하고 결합도를 낮출 수 있게 해줍니다

 

 

 

 

 

 

 

Dependency, 의존관계란?

 

 

“A가 B를 의존한다.”는 표현은 어떤 의미일까요? 추상적인 표현이지만, 토비의 스프링에서는 다음과 같이 정의합니다.

의존대상 B가 변하면, 그것이 A에 영향을 미친다.

- 이일민, 토비의 스프링 3.1, 에이콘(2012), p113

 

 

 

의존성이란 한 객체가 다른 객체를 사용할 때 의존성이 있다고 합니다.

 

 

즉, B의 기능이 추가 또는 변경되거나 형식이 바뀌면 그 영향이 A에 미칩니다.

 

 

 

 

 

 

의존성주입에 대한 내용은 다른 블로그에서도 많이 다루고 있으니 저번 블로그에서 다루던 회원관리 프로젝트에서 바로 적용해보겠습니다.

 

 

 

 

 

 

MemberService에서의 MemoryMemberRepository와 테스트케이스에서의 MemoryMemberRepository는 이름은 같지만 다른 객체입니다.

 

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

 

 

현재는 static이기때문에 문제가 없지만

static이 아닌 상황에서는 다른 인스턴스이기 때문에 내용물이 달라질 수 있습니다. 

 

 

 

 

그래서 construcor를 사용하여 다음과 같이 코드를 수정해줍니다.

private final MemberRepository memberRepository;

public MemberService(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
}

 

 

 

 

그리고 MemberServiceTest에 BeforeEach를 넣어줍시다.

@BeforeEach
public  void beforeEach(){
    memberRepository = new MemoryMemberRepository();
    memberService = new MemberService(memberRepository);
}

 

 

이렇게 코드를 짜주면 Memberservice입장에서 직접 새로운 객체를 생성해주지 않고, 외부에서 MemberRepository를 만들어 넣어줄 수 있습니다.

 

 

 

 

 

의존성주입과 관련된 더 깊은 내용은 다음 시간에 예제로 다뤄보도록 하겠습니다.

 

 

 

 

 

MemoryMemberRepository 전체 코드

package hello.hellospring.repository;

import hello.hellospring.domain.Member;

import java.util.*;

public class MemoryMemberRepository implements MemberRepository{

    private static Map<Long, Member> store = new HashMap<>();
    private static  long sequence = 0L;

    @Override
    //store에 넣기 전에 Member의 id세팅
    public Member save(Member member) {
        member.setId(++sequence); //save할때마다 sequence값 +1
        store.put(member.getId() ,member);
        return member;
    }

    @Override
    public Optional<Member> findById(Long id) {
        return Optional.ofNullable(store.get(id)); //store에서 널이 반환될 가능성이 있기때문에 ofnullable로 감싸줌
    }

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

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

 

 

MemberService 전체 코드

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemberRepository;
import hello.hellospring.repository.MemoryMemberRepository;

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

public class MemberService {

    private final 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) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 존재하는 회원입니다.");
                 });
    }

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

    public Optional<Member> findOne(long memberId){
        return memberRepository.findById(memberId);
    }
}

 

 

 

MemberServiceTest 전체 코드

 

package hello.hellospring.service;

import hello.hellospring.domain.Member;
import hello.hellospring.repository.MemoryMemberRepository;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.Optional;

import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

class MemberServiceTest {

    MemberService memberService;
    MemoryMemberRepository memberRepository;


    @BeforeEach
    public  void beforeEach(){
        memberRepository = new MemoryMemberRepository();
        memberService = new MemberService(memberRepository);
    }
    @AfterEach
    public void afterEach(){
        memberRepository.clearstore();
    }

    @Test
    void 회원가입() {

        //given
        Member member = new Member();
        member.setName("hello");

        //when
        Long saveId = memberService.join(member);


        //then
        Member findMember = memberService.findOne(saveId).get();
        assertThat(member.getName()).isEqualTo(findMember.getName());
    }


    @Test
    public void 중복_회원_예외(){
        
        //given
        Member member1 = new Member();
        member1.setName("spring");

        Member member2 = new Member();
        member2.setName("spring");
        
        //when
        memberService.join(member1);
        IllegalStateException e = assertThrows(IllegalStateException.class, () -> memberService.join(member2));

        assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");

//        try{
//            memberService.join(member2);
//            fail();
//        } catch(IllegalStateException e){
//            assertThat(e.getMessage()).isEqualTo("이미 존재하는 회원입니다.");
//        }

        //then
    }
    
    @Test
    void findMembers() {
    }

    @Test
    void findOne() {
    }
}

 

 

 

 

 

 

 

 

728x90

'Spring' 카테고리의 다른 글

10. 자바 코드로 직접 스프링 빈 등록하기  (0) 2023.04.11
9. 스프링 빈과 의존관계 (Spring)  (0) 2023.04.04
7. 비즈니스 요구사항 (Spring)  (1) 2023.04.03
Intelli J 단축키  (0) 2023.04.03
6. API (Spring 6)  (0) 2023.04.01
'Spring' 카테고리의 다른 글
  • 10. 자바 코드로 직접 스프링 빈 등록하기
  • 9. 스프링 빈과 의존관계 (Spring)
  • 7. 비즈니스 요구사항 (Spring)
  • Intelli J 단축키
minseououo
minseououo
    250x250
  • minseououo
    StudyRepository
    minseououo
  • 전체
    오늘
    어제
    • 분류 전체보기 (99)
      • 인버터 (5)
      • 자동차 (25)
      • 모터 (5)
      • 검증 (2)
      • Spring (46)
      • 프로젝트 (1)
      • 인공지능 (2)
      • 운영체제 (5)
      • Algorithm (2)
      • 소프트웨어공학 (5)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    park변환
    코깅 토크
    토크 리플
    MILS
    모터제어
    dq변환
    ISO26262
    인버터
    약계자제어
    PI제어
    java
    SDV
    clarke변환
    백앤드
    자동차 신차 개발 프로세스
    스프링
    전류 제한원
    ASPICE
    EILS
    자동차 통신
    자동차 네트워크
    자바
    mtpa
    bsw
    ASW
    자율주행
    자동차
    Spring
    AUTOSAR
    hils 검증
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
minseououo
8. 의존성 주입(dependency injection) (Spring)
상단으로

티스토리툴바