[스프링 핵심원리 기본편] 7.1 다양한 의존관계 주입

코린이서현이·2023년 11월 12일
0

🏃들어가면서🏃

달리기를 하고왔다. 아주 좋아요~ 
오늘 8장까지 듣고, 빅데이터까지 듣자. 화이팅!!!

🎯 목표

📌 다양한 의존관계 주입 방법

📌 다양한 의존관계 주입 방법

의존관계 주입의 방법

  1. 생성자 주입
  2. 수정자 주입(setter 주입)
  3. 필드 주입
  4. 일반 메서드 주입

💉 생성자 주입

  • 생성자를 통해서 의존관계를 주입받는다.

☑️ 특징

  • 생성자 호출 시점에 딱 한번만 호출, 이후 값 세팅을 막는다.
    ➡️ ⭐불변
  • 이후에는 수정할 수 없다. (변경할 수 있는 방법 자체가 없다.❌)
  • 따라서 컨테이너 빌딩 이후에는 의존관계를 변경할 수 없다.
  • ✔️ 세터 메서드를 만들지 않는다.

➡️ 필수

  private final MemberRepository memberRepository;

👉 무조건 값이 있어야하는 지정 ❣️

@Autowired를 생략해도 되는 경우

  • 생성자가 딱 하나만 있는 경우 (컴포넌트 스캔이나 스프링 빈으로 등록되어있는 경우)

💉 setter 주입 (수정자 주입)

수정자란?(setter): 필드의 값을 변경하는 수정자 메서드 (set+필드이름)
setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해서 의존관계를 주입하는 방법이다.

☑️ 특징

  • 선택 • 변경 가능성이 있는 의존관계에 사용
    @Autowired(required = false) → 주입할 대상이 없어도 동작할 수 있게 한다.
  • 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.

예제 코드

<@Component
public class OrderServiceImpl implements  OrderService{
 //주문을 받은 다음, 회원 조회 , 할인 적용을 해야한다.
  private  MemberRepository memberRepository;
  private  DiscountPolicy discountPolicy;

  @Autowired //등록된다. 
  public void setMemberRepository(MemberRepository memberRepository) {
    this.memberRepository = memberRepository;
  }
  @Autowired
  public void setDiscountPolicy(DiscountPolicy discountPolicy) {
    this.discountPolicy = discountPolicy;
  }

➕ 생성자가 없어도 된다.

❔ 그런데 우리 코드는 생성자가 있자나요..?

<스프링 생성과정> 
1. 스프링 컨테이너 생성 
2. 스프링 빈 등록
3. 스프링 빈 의존 관계 설정 - 준비
4. 스프링 빈 의존 관계 설정 - 완료 ⬅️ 바로 이시점에 의존관계 재 주입

스프링 생성 과정을 기억하시나요?

➕ 자바 빈 프로퍼티 규약 : getter, setter

  • 자바에서는 , 필드의 값을 직접 변경하지 않고, settergetter을 사용해서 수정하고, 읽게 하는 규칙이 있다.

💉 필드 주입

이름 그대로 필드에 바로 주입하는 방법이다.
➡️ 안티패턴이다. : 외부에서 변경이 불가능해서 테스트 하기 힘들다.

  • DI프레임워크가 없으면 변경할 수 없다.

😅 스프링에서 생성하는 것이 아니면 다 오류가 난다.

순수한 자바 코드로 테스트 할 수가 없다.
순수한 자바 테스트 코드에는 당연히 @Autowired가 동작하지 않는다.

@Component
public class OrderServiceImpl implements  OrderService{
 //주문을 받은 다음, 회원 조회 , 할인 적용을 해야한다.
  @Autowired private  MemberRepository memberRepository;
  @Autowired private  DiscountPolicy discountPolicy;

😣 오류

  @Test
  void fieldInjectionTest() {
    OrderServiceImpl orderService1 = new OrderServiceImpl();
    orderService1.createOrder(1L,"pizza",10000);
  }

🔨 오류 해결

  • setter을 구현해야한다. ➡️ 어처피 세터를 만들어야한다.
  @Test
  void fieldInjectionTest() {
    OrderServiceImpl orderService1 = new OrderServiceImpl();
    MemoryMemberRepository repository = new MemoryMemberRepository();
    repository.save(new Member(1L,"member1",Grade.VIP));
    orderService1.setMemberRepository(repository);

    orderService1.setDiscountPolicy(new RateDiscountPolicy());


    orderService1.createOrder(1L,"pizza",10000);
  }

😅 사용해도 되는 곳

  • 애플리케이션의 실제 코드와 관계 없는 테스트 코드
  • @SpringBootTest 처럼 스프링 컨테이너를 테스트에 통합한 경우에만 가능하다.
  • 스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용
그냥 안 쓸레요ㅎ , 괜히 복잡해지고 싶지 않아요...ㅎ

💉 일반 메서드 주입

  • 일반 메서드를 통해서 주입받을 수 있다.

☑️ 특징

  • 한번에 여러 필드를 주입 받을 수 있다.
  • 일반적으로 잘 사용하지 않는다. (수정자 주입이랑, 생성자 주입이 있으니까.)

예제코드

  @Autowired
  public void init(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
    this.memberRepository = memberRepository;
    this.discountPolicy = discountPolicy;
  }

⚠️ 참고

참고: 어쩌면 당연한 이야기이지만 의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 동작한다.
스프링 빈이 아닌 Member 같은 클래스에서 @Autowired 코드를 적용해도 아무 기능도 동작하지 않는다.

😣마무리하면서😣

요즘 계속 배가 아프다..? 왜그러지 ? 
profile
24년도까지 프로젝트 두개를 마치고 25년에는 개발 팀장을 할 수 있는 실력이 되자!

0개의 댓글