IoC(Inversion of Control)
개념을 기반으로,DI
DI
방식@Autowired
없이 생성자를 통해 주입final
키워드를 활용해 불변 객체 유지 가능@Service
public class OrderService {
private final PaymentService paymentService;
// 생성자를 통해 의존성 주입
public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void processOrder() {
paymentService.pay();
}
}
@Autowired
를 의존성을 주입받는 클래스 필드에 직접 선언하여 의존성 주입@Autowired
필드에 의존성 주입private
필드에서 의존성 주입이 가능final
을 사용할 수 없어 불변성 보장 불가❌@Service
public class OrderService {
@Autowired
private PaymentService paymentService;
public void processOrder() {
paymentService.pay();
}
}
@Autowired
를 필드 값을 변경하는 Setter
메서드에 붙여서 의존성을 주입Setter
메서드를 public
으로 열어두는 경우, 외부 변경이 가능@Service
public class OrderService {
private PaymentService paymentService;
@Autowired
public void setPaymentService(PaymentService paymentService) {
this.paymentService = paymentService;
}
public void processOrder() {
paymentService.pay();
}
}
왜 생성자 주입이 불변성을 확보할까?
final
을 사용해 필드가 반드시 할당되도록 강제 가능하다.💡Setter
주입에서는 누락이 가능해 NullPointerException
발생 위험
💡 Setter
주입과 필드 주입은 빈이 생성된 이후에 참조를 하기 때문에
애플리케이션이 아무런 오류나 경고없이 실행된다.
@Test
void testOrderService() {
PaymentService mockPaymentService = mock(PaymentService.class);
OrderService orderService = new OrderService(mockPaymentService);
orderService.processOrder();
verify(mockPaymentService).pay();
}