Spring Boot
Spring 공부 04. 의존관계주입
게슬
2023. 7. 5. 21:37
728x90
Spring에서 의존관계를 주입 할 때 여러가지 방법이 있음
1. 생성자 주입
@Autowired
//생성자가 하나면 Autowired 안 사용해도 되고
// 2개 이상이면 @Autowired 지정해 줘야함.
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
해당 방식을 사용 할 때에는 각각의 필드에 private final을 설정하는게 좋다.
2. 필드 주입
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
이렇게 사용 할 수는 있지만 권장되는 방식이 아님.
테스트 할 때에는 상관이 없지만..
3. setter 주입
@Autowired
public void setMemberRepository(MemberRepository memberRepository){
this.memberRepository = memberRepository;
}
@Autowired
public void setDiscountPolicy(DiscountPolicy discountPolicy){
this.discountPolicy = discountPolicy;
}
이렇게 사용해도 된다.
4. method주입
@Autowired // 이것도 안좋아.
void init(MemberRepository memberRepository, DiscountPolicy discountPolicy){
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
그냥 아무 method에 @Autowired를 넣어도 되는데 진자 사용하면 안되는 방식이긴함.
그다음에 @Configuration 에 직접 @Bean을 설정하는 방식도 있음
모든 주입은 순서가 보장되지 않음. 어짜피 Singleton이기 때문에 상관은 없는 방식임
그리고 의존관계 주입을 할 때에 여러가지 Option을 설정 할 수 있음.
@Autowired(required = false) // 기본값은 True임. -> 찾을 수 없으면 Error
public void setNoBean1(Member noBean1){
System.out.println("noBean1 = " + noBean1);
// Member는 Spring이 관리하는 Bean이 아님.
// required = false -> 의존관계가 없으면 호출이 되지 않는다.
}
@Autowired
public void setNoBean2(@Nullable Member noBean2){
System.out.println("noBean2 = " + noBean2);
// 호출은 되는데 의존관계가 없으면 그냥 Null로 해준다.
}
@Autowired
public void setNoBean3(Optional<Member> noBean3){
System.out.println("noBean3 = " + noBean3);
//호출은 되는데 의존관계가 없으면 그냥 Optioanl로 지정 해준다.
}
이런 방법들이 있다.
동일한 Type의 Bean이 2개 이상일 때
1. Interface type이 구체타입 직접 주입하기
이거는 설명 안해도 될거같음.
2. Qualify("{bean name}")
@Component
@Qualifier("fixDiscountPolicy")
public class FixDiscountPolicy implements DiscountPolicy
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy
이렇게 해두고
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy)
직접 넣어주면 됨
3. Primary
@Component
@Primary
public class RateDiscountPolicy implements DiscountPolicy
아니면 Primary Annotation 달아두면 이게 1순위임.
같은이름의 Bean이 2개 이상일 때 Map이나 List의 Construct가 있으면 그걸 다 주입해준다.
private final Map<String, DiscountPolicy> policyMap;
private final List<DiscountPolicy> policyList;
public DiscountService(Map<String, DiscountPolicy> policyMap, List<DiscountPolicy> policyList) {
//Map, List로 받으면 그 Interface에 해당하는 모든 Bean이 주입된다.
this.policyMap = policyMap;
this.policyList = policyList;
System.out.println("policyMap = " + policyMap);
System.out.println("policyList = " + policyList);
}
그리고 해당 Bean의 호출은 Map.get("String")으로 해주면 된다..
List는 그냥 Instance of나 find사용하면 되지 않을까..?
// method
public int discount(Member member, int price, String discountCode) {
DiscountPolicy discountPolicy = policyMap.get(discountCode);
return discountPolicy.discount(member, price);
}
// 사용
int discountPrice = discountService.discount(member, 15000, "fixDiscountPolicy");
728x90