[Spring] 의존관계 자동 주입

Seongho·2023년 1월 26일
0

Spring

목록 보기
8/13

의존관계 주입 방법

스프링 빈에 의존관계를 주입하기 위해서는 네 가지 방법이 있다.
1. 생성자 주입
2. 수정자 주입(setter 주입)
3. 필드 주입
4. 일반 매서드 주입

1. 생성자 주입

@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;
 	}
}

생성자 호출 시점에 딱 1번만 주입되고, 어떤 것도 의존관계를 변경할 수 없다. 프로그램을 컨테이너에 씌워서 배포 하고 나면 의존관계가 불변하길 원할 때 사용한다. 쉽게 말하면, 공연에서 배우들을 모두 지정하고 공연을 시작하는 것과 같다. 중간에 바뀌지 않는다.
또한, final을 사용하여 필수로 의존관계를 설정해야 할 때 사용한다.
**참고로, 생성자가 하나 있는 클래스에서는 @Autowired가 생략된다.

2. 수정자(setter)주입

@Component
public class OrderServiceImpl implements OrderService {
 	private MemberRepository memberRepository;
 	private DiscountPolicy discountPolicy;
    //
 	@Autowired			//2번 또는 3번
 	public void setMemberRepository(MemberRepository memberRepository) {
 		this.memberRepository = memberRepository;
 	}
 	@Autowired			//2번 또는 3번
 	public void setDiscountPolicy(DiscountPolicy discountPolicy) {
 		this.discountPolicy = discountPolicy;
 	}
    //생성자는 더이상 필요 없다.
    //@Autowired			//1번
 	//public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
 		//this.memberRepository = memberRepository;
 		//this.discountPolicy = discountPolicy;
 	//}
}

스프링 빈을 모두 생성한 후, setter를 통해 의존관계를 주입한다. 생성자 주입과의 차이는, 생성자 주입에서는 생성자 매서드의 파라미터를 호출하는 과정에서 다른 빈과의 의존관계가 생성과 동시에 자동으로 주입되고, setter 주입에서는 스프링 빈이 모두 등록되고, setter가 호출되며 의존관계가 주입된다. 따라서 생성자는 더 이상 필요가 없다. 선택적이고 변경 가능성이 있는 의존관계를 설정할 때 사용한다.
**참고로, 선택적으로 의존관계를 설정할 때, 주입할 대상이 없어도 동작하게 하려면
@Autowired(required = false)를 사용한다.

3. 필드 주입

@Component
public class OrderServiceImpl implements OrderService {
//
 	@Autowired
 	private MemberRepository memberRepository;
 	@Autowired
 	private DiscountPolicy discountPolicy;
}

외부에서 변경이 불가능해, 테스트가 불가능하다. 쓰지말기.

4. 일반 매서드 주입

@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를 붙여서 주입하는 방법으로, 일반적으로 사용하지 않는다. 수정자 주입과 비슷하다.

생성자 주입을 사용하자

  • 대부분 스프링 빈 의존관계 주입은 변경되는 일이 없다. 오히려, 대부분의 의존관계는 실행시간에 변하면 안된다.(불변)
  • setter 주입을 사용하면, set어쩌구 매서드를 public으로 열어두어야 하는데, 개발자의 실수를 유발한다. 또한, 변경되면 안되는 상황이 있는 로직을 매서드로 열어두는 것 자체가 잘못이다.
  • 테스트 시에 SpringBootTest가 아닌, 순수 자바 코드를 사용하여 단위 테스트를 하는 경우가 많은데, 이 경우, 테스트를 작성하는 개발자는 의존관계가 주입되는 부분의 코드를 보지 않고 있기 때문에, setter를 통한 의존관계 주입을 빼먹을 수 있다. 하지만, 컴파일 에러가 나지 않고 테스트 실패가 된다.
  • 생성자 주입을 사용하면 생성자를 호출할 때, 주입하는 파라미터(의존관계)를 누락하면 컴파일 에러가 발생하고, 필드에 final을 사용할 수 있어, 개발자의 실수를 컴파일 시점에 막아준다.
  • 결론 : 기본으로 생성자 주입 방식을 사용하고, 필수 값이 아닌 경우에는 가끔 setter 주입을 옵션으로 사용하는 것이 좋다.
profile
Record What I Learned

0개의 댓글