스프링과 빈의 의존관계

OneTwoThree·2023년 6월 18일
0

스프링 빈 이란?

  • @Controller 어노테이션이 달리면 스프링이 스프링 컨테이너에 컨트롤러 객체를 만들어 관리함
  • 이것을 스프링 빈을 관리한다고 함
  • 스프링이 인식하기 위해 @Controller @Service @Repository 와 같은 어노테이션을 달아 주는 것임
@Controller
public class MemberController {

    private final MemberService memberService;

    @Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • 서비스, 컨트롤러, 리포지토리를 모두 어노테이션을 활용해 스프링이 빈으로 인식할 수 있도록 함
  • 생성자에 @Autowired 어노테이션을 달아서 DI를 통해 알아서 객체를 외부에서 주입해주도록 함

스프링 빈 등록방법

  • 두가지 스프링 빈 등록방법이 있음. 모두 알아야 함

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

  • 위에서 어노테이션을 사용한 방식이 컴포넌트 스캔
  • @Component 어노테이션이 있으면 스프링 빈으로 자동 등록
  • 서비스, 컨트롤러, 리포지토리 어노테이션이 @Component 어노테이션을 포함해서 이 어노테이션들을 달면 스프링 빈으로 자동 등록됨
  • 스프링 빈 등록이 가능한 범위는 HelloSpringApplication이 있는 패키지와 그 하위 패키지들에서 가능함

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

  • MemberService의 @Service @Autowired , MemoryMemberRepository의 @Repository 어노테이션을 지워준다

  • SpringConfig 클래스를 만들어준다
@Configuration
public class SpringConfig {
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }
    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}
  • @Configuration 어노테이션
  • @Bean 어노테이션으로 리턴하는 객체를 스프링 컨테이너에 빈으로 등록하게 함

  • 스프링은 컨테이너에 컴포넌트를 등록할 때 기본으로 싱글톤으로 등록함(유일하게 하나만 등록해서 공유함)
  • 설정으로 싱글톤이 아니게 할 수 있지만 특별한 경우를 제외하면 거의 싱글톤 사용

DI

  • DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있음
  1. 생성자 주입
@Controller
public class MemberController {
    private final MemberService memberService;
    @Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}
  • 지금까지 사용한 방식
  • 생성자를 통해 주입함
  • 요즘 권장하는 스타일
  1. 필드 주입
@Controller
public class MemberController {
    @Autowired
    private  MemberService memberService;

//    @Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
//    public MemberController(MemberService memberService) {
//        this.memberService = memberService;
//    }
}
  • 생성자 없이 필드에 @Autowired를 달아줄 수 있음
  • 필드 주입은 뭔가 바꿀 수 있는 방법이 없음 (별로 안좋음)
  1. Setter 주입
@Controller
public class MemberController {

    private  MemberService memberService;

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

    //    @Autowired //스프링 컨테이너에서 MemberService를 의존성 주입해줌
//    public MemberController(MemberService memberService) {
//        this.memberService = memberService;
//    }
}
  • Setter에 @Autowired를 달아줌
  • 생성은 생성대로 되고 나중에 setter를 통해 주입됨
  • 단점 : Setter가 public 이어야 함 (외부에 노출이 됨)

결론

  • 생성자 주입 써라
  • 정형화된 컨트롤러, 리포지토리, 서비스는 컴포넌트 스캔 방식, 정형화되지 않거나 상황에 따라 구현 클래스를 변경해야 하는 경우 설정을 통해 스프링 빈으로 등록함
    즉 인터페이스의 구현체만 바꿔 끼워야 할 경우 유용함
    그냥 @Bean 이 달린 메소드의 리턴 객체만 바꿔주면 됨
  • @Autowired는 스프링 빈으로 등록된 객체에 대해서만 동작함

0개의 댓글