DI

강한친구·2022년 3월 28일
0

Spring 입문

목록 보기
7/10

Drill Instuctor 가 아니다.
이전시간에 학습했던 Dependency Injection이다.

이를 이해하기 위해선 스프링 컨테이너, bean을 이해해야 한다.

스프링 빈

출처

Spring IoC 컨테이너가 관리하는 자바 객체를 빈(Bean)이라고 부른다.

스프링은 처음 어플리케이션을 작동하면, 컨테이너에 Bean이라는것들을 올린다. 그리고 이 빈에 담겨있는 정보들을 이용하여 필요한것을 불러서 사용하는 방식이다.

Bean을 컨테이너에 등록하는 방법에는 두가지 방법이 있다.

Annotation

package com.example.hellospring.controller;

import com.example.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;
    }
}

membercontroller라는 파일이 있다. 이 파일은 컨트롤러 파일인데, 잘 보면 Controller라는 어노테이션이 붙어있는것을 알 수있다.

이 컨트롤러는 MemberService를 정의하고 있는데 이 MemberService는 Constructor를 통해 외부에서 memberservice를 받아서 수행한다. (받는 방법 역시 3가지 정도 있는데 추후 설명하겠다.)

그리고 이 Constructor 위에는 @AutoWired라는 Annotation이 붙어있다.

이처럼 Annotation을 붙여놓고, Spring이 실행될 때 알아서 스캔 후 빈 등록을 하도록 하는것이 바로 Annotation 방식이다.

@Component Annotation이 등록외어 있는 Spring에서는
@Repository, @Service, @Controller, @AutoWired등의 어노테이션을 사용한다.

Control

컨트롤의 경우, 이 방법 말고는 Bean에 올릴 방법이 없다. 따라서 무조건 @Control, @AutoWired를 사용해야만 한다.

Singleton

스프링은 기본적으로 싱글톤(하나만 등록해서 사용)을 한다. 따라서 두 서비스가 Repositroy에 접근하더라도 메모리를 절약할 수 있다.

Config Coding

package com.example.hellospring;

import com.example.hellospring.repository.MemberRepository;
import com.example.hellospring.repository.MemoryMemberRepository;
import com.example.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();
    }
}

Application과 같은 level에 Springconfig 파일을 만들고 그 안에 @Bean을 붙인 코드들을 생성한다.

위의 예제에서는 서비스와 레포지토리의 Bean을 만들었다.

DI의 3가지 방법

필드 주입

package com.example.hellospring.controller;

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

@Controller
public class MemberController {

   @Autowired private final MemberService memberService;

이렇게 바로 Autowird 해주는 방식이다. 절대 권장하지 않는다

setter 주입

@Controller
public class MemberController {

    private final MemberService memberService;

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

다만 이러한 문제점은 실무에서 한번 setting을 하고나면 바꿀일이 없는것들도 실수로 바꾸게 될 수도 있다는 문제점이 있다.

Constructor 주입

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

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

가장 많이 쓰이는 방법이다

왜 직접 코드입력을?

이는 나중에 아무런 코드변경없이 리포지토리를 변경할 때 자바코드 방식을 사용하면 좋기때문에 이렇게 사용한다.

실무에서는 정형화된 컨트롤러, 서비스, 리포지토리 코드는 컴포넌트 스캔(annotation)을 이용하지만, 상황에 따라 구현 클래스가 변하는 경우나 정형화되지 않은 경우라면 spring bean을 이용한다.

0개의 댓글