생성자 주입 (@RequiredArgsConstructor, @Autowired)

정병웅·2024년 3월 3일
0

back-end

목록 보기
1/2

인프런 김영한 강사님의 강의를 듣고 개인적으로 정리 하기 위해서 작성한 글 입니다!📖

생성자 주입이란?

  • 스프링에서 애플리케이션을 기동할 때(실행 할 때,,?) 각 객체들(빈 등록을 위한)을 생성 하면서 의존성을 주입하기 시작하는데, 이때 생성자의 정보를 갖고, 의존 관계를 주입하는 것을 의미한다.

@Autowired를 사용하여 주입 하는 방식


@Component
public class OrderServiceImpl implements OrderService {
    @Autowired
    private MemberRepository memberRepository;
    @Autowired
    private DiscountPolicy discountPolicy;

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

코드 설명

OrderServiceImpl 클래스에 @Autowired 어노테이션을 필드 객체에 직접 선언하였다.

문제점

  1. 스프링이 아닌 일반 자바로 작성하는 테스트 코드에서 MemberRepository의 객체를 다른 객체로 바꿔서 테스트 할 수가 없다.
    -> 만약 다른 객체를 주입 받으려면 아래의 코드처럼 setter 메서드를 추가 하여 OrderServiceImpl 클래스의 코드를 수정해야한다.

@Component
public class OrderServiceImpl implements OrderService {
    @Autowired
    private MemberRepository memberRepository;
    @Autowired
    private DiscountPolicy discountPolicy;
    
    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }
    ,,, 생략 ,,,
}
  1. 1번의 문제로 인해 setter 메서드 수정자 주입 방법으로 사용되고, 코드의 가독성 또한 떨어진다.

@RequiredArgsConstructor를 사용 주입

@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice) {
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);
        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

코드 설명

롬복 어노테이션인 RequiredArgsConstructor 어노테이션을 클래스 위에 선언을 해준다.
필드에 선언된 객체에 final 을 명시한다.
위의 방법으로 코드를 작성하게 되면 컴파일 후에 아래 코드 예시 처럼 롬복에서 final이 붙은 필드는 생성자 주입이 되도록 컴파일 해준다.

-> 생성자 주입과 동일한 코드가 된다!


@Component
public class OrderServiceImpl implements OrderService {
    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;

    public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
        this.memberRepository = memberRepository;
        this.discountPolicy = discountPolicy;
    }
	,,, 생략 ,,,
}

장점(왜 써야할까?🤔)

  1. OrderServiceImpl 객체를 생성하게 되는 코드를 작성 할 때, 기본 생성자에 해당 필수 파라미터 값이 컴파일 시점에 체크가 가능하기 때문에 명확한 코드를 작성 할 수 있다.
  2. final은 필수로 값 setting이 필요하며, 생성자 주입 시 에만 사용이 가능하다.
    -> DI 에서는 왠만하면 객체 관계 주입 이후에 바뀔 일이 없다.
  3. 롬복을 사용하는 최신 트렌드의 코드 작성 방법이다.
profile
인생은 IT 노가다

0개의 댓글