재사용성을 높여준다.
테스트에 용이하다.
코드를 단순화 시켜준다.
사용하는 이유를 파악하기 수월하고 코드가 읽기 쉬워지는 점이 있다.
종속성이 감소하기 때문에 변경에 민감하지 않다.
결합도(coupling)는 낮추면서 유연성과 확장성은 향상 시킬 수 있다.
객체간의 의존관계를 설정할 수 있다.
Store 객체가 Pencil 객체를 사용하고 있는 경우에 우리는 Store객체가 Pencil 객체에 의존성이 있다고 표현한다.
public class Store {
private Pencil pencil;
}
public class Pencil {
}
public class Store {
private Pencil pencil;
public Store() {
this.pencil = new Pencil();
}
}
1. 두 클래스가 강하게 결합되어 있음
2. 객체들 간의 관계가 아니라 클래스 간의 관계가 맺어지고 있음
: 위와 같은 문제점이 발생하는 근본적인 이유는 Store에서 불필요하게 어떤 제품을 판매할 지에 대한 관심이 분리되지 않았기 때문이다.
public interface Product {
}
public class Pencil implements Product {
}
public class Store {
private Product product;
public Store(Product product) {
this.product = product;
}
}
여기서 Spring이 DI 컨테이너를 필요로 하는 이유를 알 수 있는데, 우선 Store에서 Product 객체를 주입하기 위해서는 애플리케이션 실행 시점에 필요한 객체(빈)를 생성해야 하며, 의존성이 있는 두 객체를 연결하기 위해 한 객체를 다른 객체로 주입시켜야 하기 때문이다.
예를 들어 다음과 같이 Pencil 이라는 객체를 만들고, 그 객체를 Store로 주입시켜주는 역할을 위해 DI 컨테이너가 필요하게 된 것이다.
public class BeanFactory {
public void store() {
// Bean의 생성
Product pencil = new Pencil();
// 의존성 주입
Store store = new Store(pencil);
}
}
이러한 개념은 제어의 역전(Inversion of Control, IoC)라고 불리기도 한다.
어떠한 객체를 사용할지에 대한 책임이 BeanFactory와 같은 클래스에게 넘어갔고, 자신은 수동적으로 주입받는 객체를 사용하기 때문이다. (실제 Spring에서는 BeanFactory를 확장한 Application Context를 사용한다.)