DI
의존성
의존한다는 것은 A 가 B 를 사용(의존)할 때 자연스레 의존 관계까지 형성됩니다.
OrderController 가 OrderService 를 생성했으니 OrderController 는 OrderService 의 메소드를 사용할 수 있습니다
OrderRepository
public class OrderRepository {
public List<Order> findAllByUserNo(Long userNo) {
OrderService orderService = new OrderService();
}
}
OrderService
public class OrderService{
public List<Order> findAllByUserNo(Long userNo) {
return sqlSessionTemplate.selectList("orderList", orderList);
}
}
이런 식으로 의존 관계도 형성 됩니다. 하지만 단순 의존한다는 것은 그만큼 위험도 큽니다. 만약 OrderService 에서 변화가 일어난다면 OrderController 의 영향은 매우 클 것입니다. 뒤에 설명할 외부에서 만들고 전달할 수 있게 interface 로 변경 해줍시다
interface OrderService
public interface OrderService {
List<Order> findAllByUserNo(Long userNo);
}
만약 OrderService 구현체가 여러 개 생기고 OrderController 가 구현체들 중 OrderServiceNOSQL 를 사용하고싶다면?
OrderServiceNOSQL
public class OrderServiceNOSQL implements OrderService{
@Override
public List<Order> findAllByUserNo(Long userNo) {
return sqlSessionTemplate.selectList("orderList", orderList);
}
}
OrderServiceNOSQL 를 의존하는 OrderController
public class OrderController {
public List<Order> findAllByUserNo(Long userNo) throws InvalidUserException {
OrderServiceNOSQL orderService = new OrderServiceNOSQL();
}
}
이러면 관계는 이렇게 됩니다
OrderController 가 OrderServiceNOSQL 를 알고있기에 굉장히 불필요한 관계가 형성됩니다. 해결법은 주입을 설명하고 난 후 하겠습니다
주입
주입 이라는 것은 외부에서 만들어 준 것을 가져오는 걸 말합니다. 외부에서 만든 오브젝트를 전달 받으려면 메소드 파라미터나 생성자 파라미터를 이용해야합니다.
생성자 메소드가 추가된 OrderController
public class OrderController {
private final OrderService orderService;
public OrderController(OrderService orderService) {
this.orderService = orderService;
}
}
런타임 시점에서 런타임 오브젝트 의존 관계를 설정하는 책임이 있어야합니다
런타임시점 ApplicationEntry
public class ApplicationEntry {
public static void main(String[] args) {
OrderService orderService = new OrderServiceNOSQL();
OrderController orderController = new OrderController(orderService);
}
}
이렇게 해주면 OrderService 에서 변화에 있어도 사용하고 있는 OrderController 에선 서로 영향을 주지 않고 OrderService 는 자유롭게 확장이 가능하게 되었습니다. 런타임 시점에 OrderController 에 무슨 구현체가 주입될 지 결정되니 OrderController는 자기 역할에만 충실하면 되는 것입니다