의존관계 자동 주입

무삭이의 개발일지·2023년 3월 7일
0

inflearn Spring 핵심원리 -기본 김영한 강사님 자료 참고

생성자 주입

그 전에는 클래스에 @Component를 추가 하고 생성자에 @Autowired를 추가해서 생성자 주입 해왔는데 생성자 호출 시점에 딱 1번만 호출되는 것을 보장하면서 불변, 필수 의존관계에 사용한다. 개발에서는 불변이 중요하다!!!

수정자 주입

setter라 불리는 필드의 값을 변경하는 수정자 메서드를 통해 의존관계를 주입하는 방법
선택, 변경 가능성이 있는 의존관계에 사용
자바빈. 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법.
set에 상단에 똑같이 @Autowired를 추가 해주면 된다.

--> 이 두가지를 보통 사용하기 때문에 작성해보았다.

옵션 처리

주입할 스프링 빈이 없어도 동작해야 할 때가 있다.
그런데 @Autowired만 사용하면 required 옵션의 기본값이 true로 되어 있어서 자동 주입 대상이 없으면 오류가 발생한다.

자동 주입 대상을 옵션으로 처리 해보자.
@Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨...
@Nullable : 자동 주입할 대상이 없으면 null이 입력된다.
Optional<> :자동 주입할 대상이 없으면 Optional.empty가 입력된다.

🎯생성자 주입을 선택해야한다!!!
최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장!!!!!

불변이라는 장점이 있는데!!!
대부분의 의존관계 주입은 한 번 일어나면 애플리케이션 종료시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료전까지 변하면 안된다.(불변해야한다.)
수정자 주입을 사용하면, setXxx메서드를 public으로 열어두어야한다.
누군가 실수로 변경할 수 도 있고, 변경하면 안되는 메서드를 열어는 것은 좋은 설계 방법이 아니다.
생성자 주입은 객체를 생성할 때 딱 1번만 호출되므로 이후에 호출되는 일은 없다. 따라서 불변하게 설계할 수 있다.

누락
생성자 주입을 사용하면 주입 데이터를 누락시 컴파일 오류가 발생한다.

final키워드
생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있다. 그래서 생성자에서 호깃라도 값이 설정되지 않는 오류를 컴파일 시점에 막아준다!!!

🎯수정자 주입을 포함한 나머지 주입 방식은 모두 생성자 이후에 호출되므로, 필드에 fianl 키워드를 사용할 수 없다. 오직 생성자 주입만이 가능하다...!!

롬복과 최신 트렌드..?


롬복 라이브러리가 제공하는 @RequiredArgsConstructor 기능을 사용하면 final이 붙은 필드를 모아서 생성자를 자동으로 만들어준다.


롬복은 신이다.. 롬복으로 이제 DI가 굉장히 편해진 걸 알 수 있다. 코드도 넘모 깔끔하고. 건배..!!

조회 빈이 2개 이상일 때는 어떻게 해야할까?

FixDiscountPolicy, RateDiscountPolicy에 각각 @Component가 추가 되어있다고 가정 하고 테스트 코드를 돌리면 NoUniqueBeanDefinitionException이 발생한다. 하나의 빈을 기대했는데 두 개가 발견 되었다고 알려준다. 이 때 의존 관계 자동 주입에서 해결 하는 여러 방법이 있다!!

@Qualifier 사용
@Qualifier는 추가 구분자를 붙여주는 방법이다. 주입시 추가적인 방법을 제공하는 것이지 빈 이름을 변경 하는 것은 아님..

사진과 같이 @Qualifier을 추가 해주고 이름도 설정한다. 그리고 그 후 생성자에Qualifier 애노테이션에 이름을 설정해주면 자동으로 설정된 구현객체를 주입해준다.
@Qualifier로 주입할 때 @Qualifier("mainDiscountPolicy)를 못 찾으면 어떻게 될까? 그러면 mainDiscountPolicy라는 이름의 스프링 빈을 추가로 찾는다. 하지만 경험상 @Qualifier는 @Qualifier를 차는 용도로만 사용하는 것이 명확하고 좋다..

@Primary사용
@Primary는 우선순위를 정하는 방법이다. @Autowired시에 여러 빈이 매칭되면 @Primay가 우선권을 갖는다.
@Qualifier처럼 애노테이션을 붙여주면 끝이다. 하지만 Qualifier와는 다르게 생성자에 애노테이션를 붙여줄 필요가 없다. 깔끔하고 더 보기 좋다.
메인을 @Primary로 서브를 @Qualifier로 설정 해주면 깔끔한 코드를 유지할 수 있다.
@Qualifier가 매우 상세하고 @Primary는 기본값처럼 동작을 하기 때문에 우선순위는 @Qualifier가 높다.

애노테이션 직접 만들기

@Qualifier("mainDiscountPolicy") 이렇게 문자를 적으면 컴파일시 타입 체크가 안된다. 그러면 애노테이션으로 해결 가능하다.

@Qualifier 사용을 위한 애노테이션을 하나 만든다.

주입할 구현 객체에 직접 추가해준다.

주입할 곳에도 추가해준다.

조회한 빈이 모두 필요할 땐, List, Map

의도적으로 정말 해당 타입의 스프링 빈이 다 필요한 경우가 있다.
클라이언트가 할인의 종류 (rate, fix)를 선택할 수 있다고 가정했을 때, 어떻게 할까?

DiscountService는 Map으로 모든 DiscountPolicy를 주입 받는다. 이때, fixDiscountPolicy, rateDiscountPolicy가 주입된다.
discount()메서드는 discountCode로 "fixDiscountPolicy"가 넘어오면 map으로 fixDiscountPolicy스프링 빈을 찾아서 실행한다.

profile
No. Try not. Do or Do not. There is no try.

0개의 댓글