스프링 빈과 의존관계

inho ha·2022년 2월 11일
0

의존관계

컨트롤러에서 서비스를 통해서 조회, 등록한다 -> 컨트롤러가 서비스를 의존한다

@Controller

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
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

이렇게 컨트롤러 어노테이션을 사용하면 스프링 컨테이너에 해당 컨트롤러가 생성되어 관리된다.
이때 memberService는 new로 생성할때 다른 컨트롤러에서 해당 서비스를 사용하게 될때 중복 생성될 수도 있기 때문에 new 대신 @Autowired 로 스프링 컨테이너에 등록하여 사용하면 중복 생성을 막을 수 있다.

@Autowired 로 의존성 주입하는 것

스프링 빈을 등록하는 방법

  1. 컴포넌트 스캔과 자동 의존관계 설정
    @Controller, @Service, @Repository 는 @Component를 포함하고 있음
    이렇게 @Component로 설정된 것은 스프링이 객체를 생성해서 스프링 컨테이너에 등록함
    @Autowired 는 의존관계를 설정해줌
    실행시키는 메인 메서드의 패키지의 하위 패키지에 있는 컴포넌트 들만 스캔함
    스프링은 스프링 컨테이너에 스프링 빈을 등록할때 기본적으로 중복 생성하지 않고 하나만 생성하여 공유함
    따로 설정을 통해서 따로 생성하도록 할 수 있긴하지만 잘안씀

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

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

직접 설정 파일에 등록하는 방법

package hello.hellospring.service;

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

컨트롤러는 @Controller, @Autowired 를 설정해주고
서비스와 레포지토리는 config 클래스를 생성해서 @Configuration, @Bean 으로 직접 빈 등록해준다.
과거에는 자바 코드가 아니라 xml로 하였으나

DI

  1. 필드 주입
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 {
    @Autowired private MemberService memberService;
}

중간에 바꿀수 있는 방법이 없어서 별로임

  1. setter 주입
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 MemberService memberService;

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

set 을 하려면 public으로 열려있어야 하는데 한번 set 이후 다시 set 하지 않는데 public으로 열려 있으므로 별로임
개발에서 호출되면 안되는 것은 막아두는 것이 좋음

  1. 생성자 주입
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
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}

의존관계가 실행중에 동적으로 변하는 경우(동적으로 변해야 할때는 주로 서버를 내리고 다시 올림)는 없으므로 생성자 주입을 권장함

정형화된 컨트롤러, 서비스, 리포지토리는 컴포넌트 스캔으로 하고
상황에 따라 쿠현 클래스를 변경해야하면 자바 코드로 직접 빈 등록하여 사용함

IntelliJ 단축키

cmd + p : 함수 () 안에서 단축키 사용시 필요한 인자 확인 가능

profile
iha / ian / inho ha

0개의 댓글