728x90

의존관계 주입은 크게 4가지 방법이 있다.

1. 생성자 주입

2. 수정자 주입(setter 주입)

3. 필드 주입

4. 일반 메서드 주입

 

1. 생성자 주입

생성자에 @Autowired 가 된 것을 볼 수 있다. 첫번째로 스프링 컨테이너가 컴포넌트 스캔을 하고 OrderServiceImpl 이 @Component 가 붙어있어서 스프링 빈에 등록이 될 때, 등록이 되면 생성자가 호출 되어야 하니까, 생성자를 호출할 때 @Autowired 가 있는지 찾는다. 있으면 생성자가 요구하는 파라메터들의 타입들(여기서는 MemberRepository, DiscountPolicy) 를 가지고 있는 스프링 빈을 스프링 컨테이너가 꺼내서 주입을 시켜준다. 

 

  • 이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법이다.
  • 지금까지 우리가 진행했던 방법이 바로 생성자 주입이다.
  • 특징
    • 생성자 호출시점에 딱 1번만 호출되는 것이 보장된다.
    • 불변, 필수 의존관계에 사용

여기서 불변은 누군가가 수정하는 메서드를 만들지 않는 이상 딱 한번만 호출되기 때문에 변하지 않는다. 개발에서 불변이라는 것이 정말 중요하다. 개발 습관에서 한계점, 제약이 있어야 한다. 다 퍼블릭으로 열어두면 뭐가 수정이 되었는지 어디서 수정되었는지 알 수 없어진다. 생성자를 통해서만 의존관계가 주입이 되고 어디서도 생성자에서 설정 된 인스턴스들이 수정되는 메서드가 있어서는 안된다. 왜냐하면 개발자의 의도는 처음에 AppConfig 로 스프링 컨테이너에 빌딩되어서 올라갈 때 연관관계를 다 만들고 더이상의 수정 없이 끝내고 싶어 한것이다. 예를 들어, 공연 도중에 배우들을 바꿀 일이 없고, 공연이 시작하기 전에 배우들을 다 정해놓고 끝내고 싶은 것이다. 결론적으로 값을 세팅하고 더이상 값을 바꾸면 안될때, 가급적으로 생성자 에다가 값을 넣고 수정자 메서드(setter 메서드) 를 만들지 않으면 된다. 이렇게 하면 버그도 줄일 수 있다. 

여기서 필수는 필드에 변수들이 final 로 정의를 해야한다는 의미이다. final 로 변수를 정의 하면 꼭 그 변수에 할당되는 값이 있어야 한다. 값이 무조건 있어야 할 때를 가리킨다.(특히 생성자에 들어가는 값들) 

 

중요: 생성자가 하나만 있으면 @Autowired 가 안붙어 있어도 인식을 해서 의존관계 주입이 일어난다.

 

2. 수정자 주입

  • setter 라 불리는 필드의 값을 변경하는 수정자(setter) 메서드를 통해서 의존관계를 주입하는 방법이다.
  • 특징
    • 선택, 변경 가능성이 있는 의존관계에 사용
    • 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.

이렇게 각 타입별로 setter 들을 만들고 각각에 @Autowired 를 붙여도 의존관계 주입이 된다. 그러나 @Autowired가 없으면 안된다. 

 

여기서 스프링 컨테이너의 라이프사이클을 말해보면, OrderServiceImpl 을 스프링 컨테이너에 등록을 한다. 그 다음에 두 가지로 나뉘는데 첫 번째는 스프링 빈을 등록하고, 의존관계를 자동으로 주입한다.( @Autowired 가 걸린 애들을 연관관계를 주입시킨다 ) 해당 방법(setter 주입)은 스프링 빈을 등록하고 의존관계 주입 준비 단계 에서 일어날 때 일어난다. 생성자 주입은 하나의 인스턴스가 스프링 빈에 등록이 되면서 생성자로 바로 다른 것들도 스프링 빈이 등록되기 때문에 선택적으로 주입하는게 아니라 필수적으로 주입이 된다.

 

참고: @Autowired 의 기본 동작은 주입할 대상이없으면 오류가 발생한다. 주입할 대상이 없어도 동작하게 하려면 @Autowired(required = false) 로 지정하면 된다

생성자 주입이랑 수정자(setter)주입 이 함께 쓰이면 어떻게 될까??

생성자로 부터 인스턴스가 주입이 되고 그 다음 순서 상관없이 수정자 주입으로 인스턴스가 주입된다. 몰론 여기서도 스프링 컨테이너는 싱글톤을 보장해주기 때문에 생성자로 주입된 인스턴스들과 setter 로 주입된 인스턴스들은 모두 같은 객체들이다.

 

3. 필드 주입

  • 이름 그대로 필드에 바로 주입하는 방법이다.
  • 특징
    • 코드가 간결하지만 외부에서 변경이 불가능해서 테스트 하기 힘들다는 치명적인 단점이 있다.
    • DI 프레임워크가 없으면 아무것도 할 수 없다.
    • 사용하지 말자!
      • 애플리케이션의 실제 코드와 관계 없는 테스트 코드 에서는 괜찮다.(스프링 강좌 24분에 예시 나옴)
      • 스프링 설정을 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용

 

이렇게 하면 문제점이 setter 가 필요하다. 필드 주입을 사용할 바에는 setter 주입을 사용하는 것이 나은 형상이다.

 

4. 일반 메서드 주입

  • 일반 메서드를 통해서 주입 받을 수 있다.
  • 특징
    • 한번에 여러 필드를 주입 받을 수 있다.
    • 일반적으로 잘 사용하지 않는다.

 

그냥 메서드 위에 @Autowired 있고 이 메서드를 통해 의존관계 주입을 해준다. 사실상 수정자 주입이랑 같다. 이것을 생성자 주입이랑 수정자 주입에서 다 해결하기 때문에 이것을 사용할 일은 거의 없다.

 

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

+ Recent posts