DI가 구현에 대한 의존성을 제거하는 유일한 방법은 아니다. 이 작업을 수행하는 데 사용할 수 있는 또 다른 패턴으로 Service Locator가 있다. Service Locator 패턴을 따르는 경우엔 애플리케이션이 service locator에게 필요한 서비스를 메시지로 직접 요청하는 형태를 띄게 된다. 반면 DI의 경우엔 명시적인 요청 없이 서비스가 주입된다. 이런 형태를 일반적으로 'Inversion of Control' 이라 한다.
아래는 마틴 파울러가 15년전 작성한 글인데 정말 좋다.
https://martinfowler.com/articles/injection.html
DI 구현방식
DI엔 constructor injection, setter injection, field injection의 세가지 방식이 있다. 그리고 이 중에선 일반적으로 constructor injection 방식이 가장 권장된다. Constructor injection 방식을 쓰면 생성자만 보고도 의존 관계와 복잡성을 쉽게 알 수 있게 되기 때문에 작성하는 코드가 올바른 방향으로 가고 있는지 알 수 있게 된다. 그리고 final 키워드를 이용해 객체의 상태를 변하지 않게 만들 수 있다. 이는 setter, field injection 방식에서는 가질 수 없는 형태다.일반적으로 객체를 생성할 땐 가능하면 하나의 방식을 갖는 것이 좋고, 의존 관계가 있다면 setter method 보다 매개 변수가 있는 생성자를 통해 드러내는 것이 좋다고 알려져 있다. (객체를 구성하는 방법이 여러개라면 Factory Methods를 쓰고..) 이와 비슷한 맥락에서 DI도 constructor injection 방식을 권장하는게 아닌가 한다.
반대로 setter injection의 경우엔 특정 의존 관계를 인스턴스의 생성 시점과 구분해서 지정하거나 또는 지정하지 않거나, 교체할 수 있는 형식을 가질 수 있기 때문에 setter injection 방식도 쓰임새가 있다.
[코드 예시: https://multifrontgarden.tistory.com/214]