프로그래밍 기초

스프링 기본편 - 의존 관계 주입

sumni0530 2022. 7. 15. 23:17

스프링에서의 의존 관계 주입은 스프링 빈에 등록되어 있는 값을 매핑하여 원하는 객체를 생성하는 것을 의미한다.

인터페이스의 여러 후보들 중에서 사용할 값을 지정한 것이 스프링 빈에 등록된 것이고,

의존 관계 주입은 인터페이스를 그대로 사용했을 때, 구현체와 매핑하기 위해 사용한 방법이라고 생각하면 된다.

 

주입에 대상이 되는 메서드/변수에 @Autowired 에너테이션을 추가하여 의존 관계를 주입할 수 있으며, 4가지로 분류할 수 있다.

  1. 생성자 주입 : 생성자를 통해서 의존 관계를 주입받는 방법
    • 생성자 호출 시점에 1번만 호출되는 것을 보장하며, 필수 & 불편 의존 관계에서 사용
    • 생성자가 1개일 때는 자동으로 @Autowired로 등록됨
  2. 수정자 주입 : setter 메서드를 통해서 의존 관계를 주입하는 방법
    • 변경 가능성이 있는 의존 관계에서 사용하며, 선택 & 변경 의존관계에서 사용
  3. 필드 주입 : 필드에 바로 주입하는 방법
  4. 일반 메서드 주입 : 임의의 메서드에 의존 관계를 주입하는 방법 

다양한 의존 관계 주입 방법이 있지만 생성자 주입을 권장하며 이유는 아래와 같다.

  • 불변 : 의존 관계 주입은 애플리케이션 종료 시점까지 의존 관계를 변경할 일이 없음
  • 누락 : 프레임워크 없이 순수한 자바 코드를 단위 테스트하는 경우에 어떤 값을 필수로 주입해야하는지 에디터에서 확인 가능
  • final 키워드를 넣을 수 있으며, 이로 인해 실수로 누락된 코드에 대해서 컴파일 오류를 통해 확인 가능

@Autowired를 통해서 의존 관계를 주입할 때는 @Component와 같이 스프링 컨테이너가 관리하는 스프링 빈만 사용 가능하며, 등록되지 않은 객체에서 @Autowired를 적용 시 의존 관계는 주입되지 않는다.

 

의존 관계 주입 옵션 - 의존 관계 주입 시 스프링 빈을 찾지 못하는 경우를 처리하는 방법

  • @Autowired(required = false) : 스프링 빈이 없으면 아예 호출되지 않음
  • 파라미터 내에 @Nullable : 스프링 빈이 없으면 null 반환
  • 파라미터 타입을 Option으로 지정 : 스프링 빈이 없으면 Optional.empty 반환

 

@Autowired 이외에 의존 관계를 주입하기 위해서 lombok의 @RequiredArgsConstructor 에너테이션을 활용할 수 있다.

@RequiredArgsContruct - final 키워드가 있는 클래스 변수의 의존 관계 주입을 포함한 생성자를 만드는 에너테이션 으로 아래 두 코드 블록은 동일한 코드이다.

// @Autowired 에너테이션을 사용한 생성자 주입
@Component
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

	@Autowired // 생성자가 1개이기 때문에 생략 가능
    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
}
// @RequiredArgsConstructor 에너테이션을 사용한 생성자 주입
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final  DiscountPolicy discountPolicy;
}

 

조회 대상 빈이 2개 이상일 때 해결 방법

 

  1. @Autowired 필드 명 매칭
    • 기본적으로 타입 매칭 시도 -> (1개만 있을 시) 해당 빈 매칭 /(2개 이상 시) 필드 명, 파라미터 이름으로 빈 이름을 매칭 
  2. @Qualifier 사용
    • 추가 구분자를 붙여주는 방법으로 추가 식별자를 제공하는 것이지 빈 이름을 변경하는 것은 아님
    • 스프링 빈에 등록된 객체 중 동일한 @Qualifier 값으로 지정된 빈을 매핑
      → 못찾을 때 @Qualifier 이름으로 지정된 스프링 빈을 매핑
    • @Qualifier 를 찾는 용도로만 사용하는 것을 권장 
  3. @Primary 사용
    • @Primary가 붙어 있는 경우 우선적으로 사용
    • 코드를 깔끔하게 짤 수 있어 기본적으로 Primary 사용하고, 안되면 Qualifier를 사용

Qualifier 를 사용할 때 문자를 식별자로 사용하기 때문에 컴파일 타임에 에러를 잡지 못한다.  그래서 Qualifiter를 직접 사용하지 않고, 에너테이션을 구현하여 사용하는 것이 에러를 방지하는 방법 중 하나이다.

// Qualifier 에너테이션 기본 사용법 
@Qualifier("mainDiscountPolicy")

// 에너테이션 생성 후 사용하는 방법 (생성은 아래 참고)
@MainDisocuntPolicy

// Qualifier 에너테이션을 기반으로 새로운 에너테이션을 생성
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}

 

이렇게 자동으로 의존 관계를 주입하는 것이 요즘 트랜드라면, 의존 관계를 수동으로 주입해야 하는 경우도 있다.

  • 직접 등록하는 기술 지원 객체
  • 다형성을 적극 활용하는 경우 (고려 필요하며, 수동으로 안하는 경우 패키지로 묶어야함)