Spring ‐ 의존관계 자동 주입 - dnwls16071/Backend_Study_TIL GitHub Wiki
📚 다양한 의존관계 자동 주입 방법
- 생성자 주입 방법✅
- 수정자 주입 방법(setter)
- 필드 주입 방법
[ 생성자 주입 방법 ]
- 생성자 호출 시점에 딱 1번만 호출되는 것이 보장된다.
- 불변, 필수 의존관계에 사용한다.
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired // 생성자가 1개만 있는 상황이라면 @Autowired를 생략해도 자동 주입 된다.
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
// ...
}
[ 수정자 주입 방법 ]
- 선택, 변경 가능성이 있는 의존 관계에 사용한다.
- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용한다.
@Component
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
@Autowired
public void setMemberRepository(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy) {
this.discountPolicy = discountPolicy;
}
}
[ 필드 주입 ]
- 필드에 바로 주입하는 방법이다.
- 코드가 간결하나 DI 프레임워크가 없다면 아무것도 할 수 없다.
@Component
public class OrderServiceImpl implements OrderService {
@Autowired private MemberRepository memberRepository;
@Autowired private DiscountPolicy discountPolicy;
// ...
}
- 결론 : 생성자 주입 방법을 선택하기
- 이유1 : 대부분의 의존관계 주입은 한 번 일어나면 애플리케이션 종료 시점까지 의존관계를 변경할 일이 없다. 오히려 대부분의 의존관계는 애플리케이션 종료 전까지 변하면 안 된다.
- 이유2 : 수정자 주입을 사용하면 결국 public으로 열어두어야 하는데 이렇게 열어두게 되면 누군가 실수로 변경할 수 있기 때문에 좋은 설계가 아니다.
- 이유3 : 생성자 주입은 객체를 생성할 때, 딱 1번만 호출되므로 이후에 호출되는 일이 없다. 따라서 불변하게 설계할 수 있다.
📚 조회되는 빈이 2개 이상인 경우 해결 방법 - @Autowired
필드명, @Qualifier
, @Primary
- 조회되는 빈이 2개 이상인 경우 NoUniqueBeanDefinitionException 예외가 발생한다.
- @Autowired 필드명 매칭
- @Qualifier
- @Primary
[ @Autowired 필드명 매칭 ]
@Autowired
private DiscountPolicy discountPolicy;
@Autowired
private DiscountPolicy rateDiscountPolicy; // 특정 빈 이름으로 변경
[ @Qualifier ]
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy {}
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy {}
[ @Primary ]
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy {}
@Component
public class FixDiscountPolicy implements DiscountPolicy {}
📚 어노테이션 커스텀 방법
// @Qualifier 어노테이션 내용에 붙은 어노테이션을 사용하면서 이름 부여
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Qualifier {
String value() default "";
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}