빙응의 공부 블로그
[Spring]스프링 핵심 원리 - 의존 관계 주입 본문
📝다양한 의존관계 주입 방법
[Spring]의존성 주입(DI) (tistory.com)
[Spring]의존성 주입(DI)
1. 의존성 주입에 대해 DI 두 객체 간의 관계를 결정해주는 디자인 패턴이다. DI는 인터페이스를 사이에 둬서 클래스 레벨에서의 의존관계가 고정되지 않도록 하고 런타임 시에 관계를 동적으로
quddnd.tistory.com
- 생성자 주입
- 수정자 주입
- 필드 주입
- 일반 메서드 주입
생성자 주입
이름 그대로 생성자를 통해서 의존 관계를 주입 받는 방법이다. 특징은 다음과 같다.
- 생성자 호출시점에 딱 1번만 호출되는 것을 보장(싱글톤)
- 불변, 필수 의존관계에 사용
- 불변 : 프로그래밍에는 모든 가능성을 열어두지 않고 불변성을 지켜야 하는 부분이 존재한다.
- 필수 : 생성자에는 값을 무조건 넣는 필수 값을 사용한다.
@Component
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository;
private final DiscountPolicy discountPoilcy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPoilcy) {
this.memberRepository = memberRepository;
this.discountPoilcy = discountPoilcy;
}
참고! 생성자가 딱 1개있는 생성자이면 @Autowired를 생략해도 자동 주입된다. 개인적으로 그냥 사용하여 표시하는게 좋을 것 같다.
수정자 주입
setter(필드 값 변경 메소드)를 이용하여 의존 관계를 주입하는 방식이다. 특징은 다음과 같다.
- 선택, 변경 가능성이 있는 의존관계에 사용한다.
- 자바빈 프로퍼티 규약의 수정자 메서드 방식을 사용하는 방법이다.
- 자바빈 프로퍼티 규약 : set, get 메서드를 이용하여 값을 읽거나 수정하는 규칙이다.
@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;
}
}
참고! @Autowired의 기본 동작은 주입할 대상이 없으면 오류가 발생해 @Autowired(required = false)를 지정
필드 주입
이름 그대로 필드에 값을 넣어버리는 것, 특징은 다음과 같다.
- 코드가 간결하여 좋을 것 같지만 외부에서 변경이 불가능해서 테스트하기 매우 힘들다.
- DI 프레임워크가 없으면 사용 불가능
- 걍 사용하지마!
@Component
public class OrderServiceImpl implements OrderService {
@Autowired
private MemberRepository memberRepository;
@Autowired
private DiscountPolicy discountPolicy;
}
일반 메서드 주입
일반 메소드를 통해서 주입 받을 수 있다. 특징은 다음과 같다.
- 한번에 여러 필드를 주입 받을 수 있다.
- 일반적으로 잘 사용하지 않는다.
@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;
}
}
📝옵션 처리
주입할 스프링 빈이 없어도 동작해야 할 때가 있다.
그런데 @Autowired를 사용하면 오류가 발생한다.
자동 주입 대상을 옵션으로 처리하는 방법은 다음과 같다.
- @Autowired(required=false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨
- org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력된다.
- Optional<> : 자동 주입 대상이 없으면 Optional.empty가 입력된다.
@Test
void AutowiredOption(){
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(TestBean.class);
}
@Component
static class TestBean{
@Autowired(required = false)
public void setNoBean1(Member member){
System.out.println("member1 = "+ member);
}
@Autowired
public void setNoBean2(@Nullable Member member){
System.out.println("member2 = "+ member);
}
@Autowired
public void setNoBean3(Optional<Member> member){
System.out.println("member3 = "+ member);
}
}
📝다양한 의존 관계 주입 결론
생성자 주입을 사용해라!
과거에는 수정자 주입과 필드 주입을 많이 사용하였다.최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다.
불변
클린코드에서 불변성을 지키는 것은 중요한 부분이다.
- 대부분의 의존관계 주입은 한번 일어나면 변경되는 일이 없다.
- 누군가 실수로 변경할 수도 있고, 변경하면 안되는 메소드를 열어두는 것은 좋은 클린 코드가 아니다.
누락
프레임워크 없이 순수한 자바 코드를 단위 테스트 하는 경우에 다른 테스트는 의존관계 주입이 누락될 수 있다.
그 이유는 프레임워크에 의존하기 때문에 다른 주입 사용 시 테스트하기 어렵다.
@Test
void createOrder() {
OrderServiceImpl orderService = new OrderServiceImpl();
orderService.createOrder(1L, "itemA", 10000);
}
final 키워드
생성자 주입을 사용하면 필드에 final 키워드를 사용할 수 있다. 그래서 생성자가 혹시라도 값이 설정되지 않는 오류를 컴파일 시점에서 막아준다.
@Component
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
@Autowired
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy
discountPolicy) {
this.memberRepository = memberRepository;
}
//...
}
- final 키워드를 사용하면 자바는 컴파일 시점에서 오류를 발생 시킨다.
- 컴파일 오류는 세상에서 가장 빠르고, 좋은 오류이다.
- 수정자 주입이나 필드 주입은 모두 생성자 이후 호출되기 때문에, 필드에 final 키워드를 사용할 수 없다.
'Spring > 인프런_개념' 카테고리의 다른 글
[Spring]스프링 핵심 원리 - 빈 생명주기 콜백 (0) | 2023.12.29 |
---|---|
[Spring]스프링 핵심 원리 - 의존 관계 주입2 (1) | 2023.12.28 |
[Spring]스프링 핵심 원리 - 컴포넌트 (0) | 2023.12.27 |
[Spring]스프링 핵심 원리 - 싱글톤 컨테이너 (1) | 2023.12.26 |
[Spring]스프링 핵심 원리 - 스프링 컨테이너와 빈 (0) | 2023.12.26 |