이번 시간에는 의존관계 자동 주입에 대해서 알아보았다.
먼저 다양한 의존관계 주입 방법에 대해서 다루었는데, 의존관계 주입은 크게 4가지 방법이 있다.
생성자 주입, 수정자 주입 (setter 주입), 필드 주입, 일반 메소드 주입.
각각 설명을 하자면,
1. 생성자를 통해서 의존관계를 주입하는 생성자 주입,
2. setter 메소드를 통해서 의존관계를 주입하는 수정자 주입,
3. 필드를 통해서 의존관계를 주입하는 필드 주입,
4. 일반 메소드에 의존관계를 주입하는 일만 메소드 주입이 있다.
먼저 1. 생성자 주입부터 설명하자면~~
OrderServiceImpl을 들어가보게 되면 생성자에 Autowired 된 것을 볼 수 있다.
클래스에 @Component 어노테이션이 달려 있기 때문에 ComponentScan을 할 때 스프링 빈에 등록이 된다.
등록이 되면서 생성자를 호출하고, Autowired가 달려 있으면 스프링 컨테이너에서 필요한 빈 객체를 꺼낸다.
위의 예시에서 본다면 스프링 컨테이너에서 MemberRepository, DiscountPolicy을 꺼내고 주입해준다.
생성자 주입의 특징은, 생성자 호출시점에 딱 1번만 호출되는 것이 보장된다.
다르게 말하자면, 한번 세팅이 되고, 그 다음에는 세팅 못하게 막을 수 있다는 것이다.
그렇기 때문에 불변, 필수 의존관계에 사용된다.
좋은 개발 습관은, 다 열어두지 않고 제약을 두는 것이다. 왜냐하면, 어디서 뭐가 수정되었는지 알 수 없기 때문!
위의 예시에서, 생성자를 통해서만 의존관계가 주입되기 때문에, 그 외에는 memberRepository를 수정할 수 없다.
추가로, 스프링 빈에서는 생성자가 1개만 있으면 Autowired를 생략해도 된다.
생성자가 2개 이상이 있다면, @Component 혹은 @Bean이 달린 클래스를 스캔할 때,
스프링 컨테이너가 Autowired를 어디다 해야될지 모르기 때문에 지정해줘야 한다.
테스트를 위해서, 생성자가 하나이고 Autowired가 없을 경우에는, 정상적으로 주입되는 것을 볼 수 있다.
마찬가지로, Autowired 어노테이션을 추가했을 때도, 주입이 정상적으로 되는 것을 볼 수 있다.
요즘에는 생성자 주입을 가장 많이 사용한다고 한다.
2. 수정자 주입은 setter라고 불리는 필드의 값을 변경하는 수정자 메소드를 통해서 의존관계를 주입하는 방식이다.
필드의 값을 수정할 때 관례적으로 자바 빈 프로퍼티 규약에 의해서
직접 수정하지 않고 setMemberRepository와 같이 추가해서 주입을 한다.
그리고 setMemberRepository를 수정자라고 한다.
테스트 결과, 정상적으로 값을 주입해주는 것을 확인할 수 있다.
수정자 주입의 특징은, 선택적, 변경 가능성이 있는 의존관계에서 사용한다.
예를 들어, 생성자에서 주입할 때는 필수값이였지만, memberRepository가 스프링 빈에 등록이 되어있지 않더라도,
선택적으로 의존관계를 주입하여 사용할 수 있다.
또한 중간에 인스턴스를 바꾸고 싶으면 외부에서 setMemberRepository를 호출이 가능하다.
참고로, @Autowired 의 기본 동작은 주입할 대상이 없으면 오류가 발생한다.
주입할 대상이 없어도 동작하게 하려면 required = false를 지정하면 된다.
3. 필드 주입은 필드에 직접적으로 의존관계를 주입하는 것이다.
위와 같이 필드에 직접 어노테이션을 추가해준다.
필드를 로그에 찍어보기 위해 테스트 코드를 작성하고 돌렸을 때, 정상적으로 찍히는 것을 볼 수 있다.
코드가 간결하지만, 외부에서 변경이 불가능하기 때문에 테스트 하기 힘들다는 큰 단점이 있다.
또한 DI 프레임 워크가 없으면 아무것도 할 수 없다.
그렇기 때문에 테스트 코드에서만 쓰거나, 스프링 설정 목적으로 하는 @Configuration 같은 곳에서만 특별한 용도로 사용하고, 그 외에는 쓰지 않는 것을 권장!
4. 일반 메소드 주입은 아무 Autowired 어노테이션을 추가해서 일반 메소드나 주입을 받을 수 있다.
위와 같이 일반 메소드에 @Autowired 어노테이션을 추가해서 의존관계 주입이 가능하다.
사실 수정자 주입이랑 거의 동일한 방식이라고 할 수 있다. 메소드에 Autowired가 달려 있을 뿐!
일반적으로는 잘 사용하지 않지만, 한번에 여러 필드를 주입 받을 수 있는 특징이 있다.
참고로 당연한 이야기지만, 의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야만 동작한다.
@Component나 @Bean이 달려 있기 때문이다.
스프링 빈이 아닌 Member 같은 일반 클래스에서 @Autowired 어노테이션을 적용해도 아무런 기능이 동작하지 않는다.
댓글