의존간계 주입 방법
의존관계를 주입해줄 때는 @Autowired 어노테이션을 사용한다
1. 생성자 주입
- 생성자 호출 시점에 딱 1번만 호출되는 것이 보장
- 불변, 필수 의존관계에 사용
- 생성자가 하나만 존재하면 @Autowired 생략 가능
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
2. 수정자 주입 (setter 주입)
- 선택, 변경 가능성이 있는 의존관계에 사용
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
3. 필드 주입
- 코드가 매우 간결해지지만 외부에서 변경이 불가능해 테스팅 매우 어려움
- DI 프레임워크가 없으면 아무것도 할 수 없다
- 사용 권장 X
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
4. 일반 메서드 주입
- 한 번에 여러 필드 주입 가능
- 일반적으로 잘 사용X
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void init(MemberRepository memberRepository, DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
어떤 방법이 가장 좋을까에 대한 대답은 생성자 주입 방법을 사용하는 것이다.
- 대부분 의존관계 주입이 일어나면 변경할 일이 없다. 오히려 변하면 안된다. (불변)
- 수정자 주입 사용시 public으로 열어둬야 하는데 변경 가능성 생김
Lombok 플러그인을 통한 생성자 주입
lombok 플러그인을 적용하면 @RequiredArgsConstructor을 통해 final이 붙은 필드에 대해 자동으로 생성자를 생성해준다.
@Component
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
}
생성자를 구현하지 않았지만 @RequiredArgsConstructor를 통해 자동으로 생성자가 구현되어 있음을 확인
의존 관계 매칭
@Autowired에 의해 의존 관계가 자동으로 매칭된다. 하지만 의존관계에 필요한 빈이 2개 이상이면 오류가 발생한다.
위 코드를 예시로 private fianl DiscountPolicy discountPolicy에는 자손 클래스인 fix와 rate가 들어올 수 있다.
따라서 fix와 rate 모두 빈으로 등록되어 있다면 위 코드 실행 시 오류가 발생할 것이다.
이럴 때 사용하는 것이 @Primary와 @Qualifier이다
@Primary
빈에 우선순위를 부여
@Qualifier
빈 등록시 구별자를 위한 이름 부여
조회한 빈이 여러개 필요한 경우
위 코드에서 rate와 fix 모두 필요한 경우가 있을 수 있다. 그럴 땐 아래와 같이 Map 혹은 List로 받아올 수 있다.
private final Map<String, DiscountPolicy> policyMap;
private final List<DiscountPolicy> policies;
의존 관계 주입 자동 VS 수동
@Autowired를 통한 자동 의존 관계 주입을 알아봤는데 당연히 수동으로도 등록할 수 있다.
어떤 차이가 있을까?
자동
업무 로직 빈의 경우
웹을 지원하는 컨트롤러, 핵심 비즈니스 로직이 있는 서비스, 데이터 계층의 로직을 처리하는 레퍼지토리 처럼 어느정도 유사한 패턴을 가지고 있어 이런 경우 자동 기능을 적극 사용하는 것이 좋다. 보통 문제가 발생하면 어디서 발생했는지 명확하게 파악하기 쉽다
수동
기술 지원 빈의 경우
업무 로직에 비해 로직이 매우 적고, 앱 전반에 걸쳐 광범위하게 영향을 미친다. 문제 발생 시 파악하기 힘들기 때문에 가급적 수동 빈 등록을 통해 명확하게 드러내는 것이 좋다.
기술 지원 빈
기술적인 문제나 공통 관심사 (AOP)를 처리. 또는 DB연결, 공통 로그 처리 처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술들을 말함.
'Study > Spring' 카테고리의 다른 글
[Spring] 웹 스코프 - Request (0) | 2023.08.02 |
---|---|
[Spring] 싱글톤 스코프에서 프로토타입 스코프 사용 시 문제점과 해결 방법 (0) | 2023.08.01 |
[Spring] 빈 등록 초기화(@PostContruct), 소멸 메소드(@PreDestroy) (0) | 2023.08.01 |
스프링 컨테이너의 싱글톤 패턴 (0) | 2023.07.27 |
스프링 프레임워크와 스프링 부트 (0) | 2023.07.24 |