@Autowired(required = false)
public void setNoBean1(Member noBean1) {
// 아예 호출이 안됨.
System.out.println("noBean1 = " + noBean1);
}
@Autowired
public void setNoBean2(@Nullable Member noBean2) {
// noBean2 = null
System.out.println("noBean2 = " + noBean2);
}
@Autowired
public void setNoBean3(Optional<Member> noBean3) {
// noBean3 = Optional.empty
System.out.println("noBean3 = " + noBean3);
}
불변성을 보장할 수 있다.
누락을 쉽게 감지할 수 있다. (feat. final키워드)
final
을 붙임으로써 해당 필드의 초기화가 필수임을 명시할 수 있다.final
을 붙임으로써! 생성 단계에서 필수 값들을 빠트렸는 지 쉽게 감지할 수 있다 (바로 컴파일 에러 발생됨) 그리고 IDE에서 바로 어떤 값을 필수로 주입해야 하는지 알 수 있다.테스트가 용이해진다.
// class OrderServiceImplTest {
@Test
void createOrder(){
// 순수 자바 테스트에서
// 생성자 주입의 경우, 아래와 같이 생성자 파라미터를 임의로 만들어서 넣어줄 수 있다.
MemberRepository memberRepository = new MemoryMemberRepository();
memberRepository.save(new Member(1L, "name", Grade.VIP));
DiscountPolicy discountPolicy = new RateDiscountPolicy();
OrderServiceImpl orderService = new OrderServiceImpl(memberRepository, discountPolicy);
Order order = orderService.createOrder(1L, "itemA", 10000);
Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
}
필드이름
, 파라미터 이름
으로 빈 이름을 추가 매칭한다.@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy rateDiscountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Component
@Qualifier("mainDiscountPolicy")
public class RateDiscountPolicy implements DiscountPolicy{
// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@Autowired // @RequiredArgsConstructor로 대체 가능
public OrderServiceImpl(MemberRepository memberRepository, @Qualifier("mainDiscountPolicy") DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
@Primary
메인 DB와 보조 DB를 사용할 경우, 메인 DB쪽에 @Pimary를 걸어주고, 보조 DB에는 @Qualifier를 걸어주는 방식 등을 사용한다.
항상 자세하게 접근하는 것이 우선권을 가져간다. 즉, @Qualifier가 우선권을 가진다.
// 어노테이션 @MainDiscountPolicy 정의하기
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier("mainDiscountPolicy")
public @interface MainDiscountPolicy {
}
// 필요한 곳에 붙여주기 (해당 예제에선 DiscountPolicy의 구현체)
@MainDiscountPolicy // 직접 만들어준 어노테이션
@Component
public class RateDiscountPolicy implements DiscountPolicy{
// 필요한 곳에 붙여주기 (해당 예제에선 DiscountPolicy이 의존성 주입이 일어나는 곳, 생성자 파라미터)
@Autowired // @RequiredArgsConstructor로 대체 가능
public OrderServiceImpl(MemberRepository memberRepository, @MainDiscountPolicy DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}