Spring Basic - 7

mmm·2023년 3월 28일
0

섹션 7. 의존관계 자동 주입

의존관계 주입

  • 생성자 주입
    • 생성자를 통해 의존관계 주입 (스프링 빈의 생성자가 하나일 때, @Autowired 생략 가능)
    • 생성자 호출시점에 딱 1번만 호출되는 것이 보장됨
    • 불변, 필수 의존관계에 사용
      • → 대부분의 애플리케이션은 한번 의존관계 주입 후 변경할 일이 거의 없다. 오히려 불변해야한다. 누군가 실제로 변경할 수 있으며, 변경하면 안되는 것들을 열어두는 것은 좋은 설계 방법이 아니다. 따라서 생성자 주입을 선택하여 불변하게 설계하자!
  • 수정자 주입(setter)
    • 수정자 메서드를 통해서 의존관계를 주입(setter)
    • 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법
    • 선택, 변경 가능성이 있는 의존관계에 사용
  • 필드 주입
    • 의존관계를 필드에 바로 주입
    • 코드가 간결 → 그러나 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점
    • 애플리케이션의 실제 코드와 관련없는 테스트코드, 스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용 → 이외에는 사용하지 말것!
    • DI 프레임워크가 없으면 아무것도 할 수 없음
  • 일반 메서드 주입
    • 일반 메서드를 통해 의존관계 주입
    • 한번에 여러 필드 주입 가능

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

생성자 주입을 사용 !

  • 프레임워크에 의존하지 않고, 순수한 자바 언어의 특징을 잘 살리는 방법
  • 기본으로 생성자 주입 + 필수 값이 아닌 경우에는 수정자 주입 방식을 옵션으로 부여
  • 항상 생성자 주입을 선택 + 가끔 옵션이 필요하면 수정자 주입을 선택 / 필드 주입 사용 X

최근에는 생성자를 1개만 두고, @Autowired 를 생략하는 방법을 주로 사용

  • 여기에 Lombok 라이브러리@RequiredArgsConstructor 를 함께 사용하면 기능은 다 제공하면서, 코드는 깔끔하게 사용할 수 있다.
ingframework.stereotype.Component;

@Component
@RequiredArgsConstructor    // 생성자
public class OrderServiceImpl implements OrderService{

    private final MemberRepository memberRepository;
    private final DiscountPolicy discountPolicy;
}

자동 주입 대상을 옵션으로 처리하는 방법

  • @Autowired(required = false) : 자동 주입 대상이 없으면 메서드 호출 x
  • @Nullable : 자동 주입 대상이 없으면 null
  • Optional<> : 자동 주입 대상이 없으면 Optional.empty
public class AutoWiredTest {

    @Test
    void AutowiredOption(){
        ApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
    }

    static class TestBean{
        @Autowired(required = false)
        public void setNoBean1(Member noBean1){
            System.out.println("noBean1 = " + noBean1);
        }

        @Autowired
        public void setNoBean2(@Nullable Member noBean2){
            System.out.println("noBean2 = " + noBean2);
        }

        @Autowired
        public void setNoBean3(Optional<Member> noBean3){
            System.out.println("noBean3 = " + noBean3);
        }
    }
}

/* 출력 결과 (noBean1은 member가 스프링 빈이 아니므로 메서드 호출이 안됨)
noBean2 = null
noBean3 = Optional.empty
*/
profile
mmm

0개의 댓글