Spring dependency auto injection

강정우·2023년 11월 4일
0

Spring-boot

목록 보기
13/73
post-thumbnail

의존관계 자동 주입

  • 의존관계 주입은 크게 4가지 방법이 있다.
  1. 생성자 주입 (99% 이거 사용)
  2. 수정자 주입 (setting 주입, 1% 사용)
  3. 필드 주입
  4. 일반 메서드 주입

의존관계 자동 주입은 스프링 컨테이너가 관리하는 컨테이너(스프링 빈)여야 동작한다.
스프링 빈이 아닌 일단 클래스에가서 암만 @Autowired 갖다 박아봐야 아무일도 일어나지 않는다.

생성자 주입

  • 이름 그대로 생성자를 통해서(@Autowired) 의존 관계를 주입 받는 방법이다.
  • 생성자 호출 시점에 딱 1번만 호출되는 것이 보장된다.

  • @ComponentScan(boot에서는 @SpringBootApplication)이 실행되면서 @Component를 만나면 이제 빈으로 등록하기 위해서 생성자를 호출하는데 이때 @Autowired를 만나면 스프링 컨테이너에서 생성되어있는 memberRepository 와 discountPolicy 빈을 꺼내와서 저기에 넣어준다.

  • 이때 위 코드에서는 빠졌는데 private 다음에 final을 넣어주어서 프로젝트가 뜰 때 웬만하면 값을 항상 갖고 있도록 하는 것이 좋을 것이다.

  • 이때 생성자가 1개밖에 없다면 @Autowired를 생략할 수 있다.

  • 스프링 빈이 등록될 때 한 큐에 일어난다.

  • 특징
    • 생성자 호출 시전에 딱 1번만 호출되는 것이 보장된다.
    • 따라서 "불변, 필수" 의존관계에 사용
    • 주로 생성자 주입을 사용한다.

수정자 주입

@Component
public class OrderServiceImpl implements OrderService {

//    private final MemberRepository memberRepository = new MemoryMemberRepository();
//    private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
//    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    private MemberRepository memberRepository;
    private DiscountPolicy discountPolicy;

    @Autowired
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    @Autowired
    public void setDiscountPolicy(DiscountPolicy discountPolicy) {
        this.discountPolicy = discountPolicy;
    }
    
    @Autowired
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
  • 이렇게 setting 함수에 @Autowired를 붙여도 된다.

  • 앞서 스프링 빈이 등록된 다음 -> 스프링 빈 의존관계 설정 (준비) -> 스프링 빈 의존관계 설정 (완료) 이렇게 나뒤어있다고 말했다.

  • 이를 이렇게 따로 나눴던 이유는 바로 setter 주입에 있다. 바로 이 스프링 빈 의존관계 설정을 할 때 일어난 것이다.

  • 그리고 setting 메서드가 DI를 해주기 때문에 따로 생성자 함수가 필요없어진다.

  • 그럼 생성자주입과 setter 주입의 차이는 1. 주입시점, 2. 값의 수정가능 여부 정도가 있겠다.

  • 특징
    • 선택, 변경 가능성이 있는 의존관계에 사용
    • 자바 bean property 규약의 수정자 메서드 방식을 사용하는 방법이다.
  • 앞서 선택, 변경 가능이 있다고 했는데 @Autowired의 기본 동작은 주입할 대상이 없으면 오류가 발생한다. 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false)로 지정하면 된다.

  • 앞서 "자바 빈 프로퍼티 규약" 이라고 했는데 이는 필드의 값을 직접변경하는 것이 아닌, getter, setter 메서드를 통해 값을 수정하는 규칙을 뜻한다.

필드 주입

  • 상남자 스럽긴 한데 앞서 말했던 "자바 빈 프로퍼티 규약"을 어기는 방법이다. 바로 플드에 바로 때려박는 것이다. 이는 코드를 매우 심플하게 짤 수 있다. 뭐 생성자고 setter고 다 필요없이 그냥 필드 private 앞에 @Autowired를 박으면 된다.

  • 하지만 상남자들은 오래살지 못 한다. 필드 주입 역시 예전에 쓰던 방식이고 권장하지 않는 방법이다.

  • 특징

    • 코드가 간결하지만 외부에서 변경이 불가능해서 테스트하기가 힘들다.
    • DI 프레임웤이 없으면 아무것도 할 수 없다.
    • 다만 애플리케이션의 실제 코드와 관계없는 테스트 코드에서는 괜춘
    • 또 스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용

일반 메서드 주입

  • 일반 메서드를 통해서 주입받을 수 있다.
  • 특징
    • 한번에 여러 필드를 주입 받을 수 있다.
    • 일반적으로 잘 사용하지 않는다.
// 생성자 함수
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
  this.memberRepository = memberRepository;
  this.discountPolicy = discountPolicy;
}

// 반환 타입만 추가한 아무 함수
@Autowired
public void somethingMethod(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
  this.memberRepository = memberRepository;
  this.discountPolicy = discountPolicy;
}
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글