Hi yoahn 개발블로그

[Spring] #4 스프링 빈과 의존관계 (스프링 빈 등록 방법) 본문

Framework & Library/springboot

[Spring] #4 스프링 빈과 의존관계 (스프링 빈 등록 방법)

hi._.0seon 2021. 1. 22. 16:17
반응형

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

@Controller
public class MemberController {

    private final MemberService memberService = new MemberService();
}

spring을 실행시키면 스프링 컨테이너가 생성됨

-> @Controller가 있으면 해당 클래스 객체를 생성해서 스프링에 넣어둠 

    -> 스프링이 관리  (== 스프링 빈이 관리된다)

*** 스프링이 관리하게 되면 다 스프링 컨테이너에 등록하고 스프링 컨테이너한테 받아서 쓰도록 해야한다

- 다른 여러 컨트롤러들이 객체를 new로 생성하면 여러개의 인스턴스가 생성됨

- 스프링 컨테이너에 등록하게 되면 딱 하나만 등록되어 공용으로 사용 가능

@Controller
public class MemberController {

    private final MemberService memberService;

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

@Autowired

- 생성자에 붙여놓으면 스프링 컨테이너에 있는 인스턴스를 가져와서 연결해줌

    -> Dependency Injection 의존관계 주입

- 연결된 서비스나 리포지토리에 @Service, @Repository 를 추가

-> 스프링이 뜰 때 컨트롤러 & 서비스 & 리포지토리를 다 가지고 올라옴

- @Service 생성자에도 레포지토리 객체 연결할 수 있도록 @Autowired 추가

@Service
public class MemberService {

    private final MemberRepository memberRepository;

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

스프링 빈으로 등록된 것들을 @Autowired 로 연결

컴포넌트 스캔 원리

  • @Component 가 있으면 스프링 빈으로 자동 등록된다.
  • @Component 를 포함하는 @Controller, @Service, @Repository 도 스프링 빈으로 자동 등록된다

스프링 -> 웬만한 것들은 스프링 빈으로 다 등록해서 써야 얻는 이점이 많다.

 

스프링이 시작되는 main 코드가 있는 패키지 하위에 있는 것들만 스프링이 @Component로 등록된것을 전부 찾아서 스프링 빈으로 등록 (main이 포함된 패키지 바깥에 있는 Component들은 기본적으로는 스프링 빈으로 등록 안됨)

 

참고: 스프링은 스프링 컨테이너에 스프링 빈을 등록할 때, 기본으로 싱글톤으로 등록한다(유일하게 하나만 등록해서 공유한다) 따라서 같은 스프링 빈이면 모두 같은 인스턴스다. 설정으로 싱글톤이 아니게 설정할 수 있지만, 특별한 경우를 제외하면 대부분 싱글톤을 사용한다.

 

** 싱글톤: 유일하게 하나만 등록하는 것, 인스턴스 생성을 하나만 함

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

@Controller
public class MemberController {

    private final MemberService memberService;

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

이 코드를 제외하고 Service 와 Repository 는 어노테이션 제거하고 진행

 

hello.hellospring.SpringConfig.java

@Configuration
public class SpringConfig {

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

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

@Configuration을 스프링이 읽고 @Bean 을 스프링 빈에 등록하라는 뜻이라고 이해하고 그 로직을 실행해서 스프링 빈에 등록

 

DI 방법

1. 생성자 주입

- 생성자를 통해서 DI 하는 방법

 

2. 필드 주입

@Autowired private MemberService memberService;

- 나중에 변경 불가, 나중에 바꿀 수 있는 방법이 없다(바꿔치기 불가)

 

3. Setter 주입

@Autowired

public void setMemberService(MemberService memberService)

- 생성은 생성대로 되고 나중에 setter를 통해서 주입

- 누군가가 멤버 컨트롤을 호출했을 때 메소드가 public으로 열려있어야 한다

- 중간에 실수로 바뀔 수 있음

 

-> 실행 중에 동적으로 바뀌는 경우는 거의 없고, 보통 서버를 다시 올림 -> 생성자 주입 권장

 

정형화된 컨트롤러 / 서비스 / 리포지토리는 컴포넌트 스캔 사용
정형화 되지 않거나 구현 클래스를 상황에 따라 변경해야 하면 코드를 통해 스프링 빈으로 등록
(정형화 되지 않은 코드 ex) 연결될 DB 가 정해지지 않은 경우, 나중에 설정파일만 건드리면 된다
@Autowired 를 통한 DI는 helloConroller , memberService 등과 같이 스프링이 관리하는
객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다.
: 스프링 빈으로 등록된 객체만 Autowired 가능

 

 

 

반응형
Comments