DI(Dependency Injection)
- 객체를 직접 생성하는 것이 아니라, 외부에서 생성한 후 주입 시켜주는 방식
- 생성자, setter를 통해 외부에서 생성된 객체를 사용한다.
- 스프링에서는
@Autowired
를 통해 의존성을 주입한다.(생성자, 필드, setter에 사용)
- 스프링이 프레임워크가 필요한 객체를 생성해서 관리해주기 떄문에, 이미 생성된 객체를 원하는 곳에서 사용(주입)하면 된다.
- 빈(Bean) : 스프링이 관리하는 객체
- 스프링 IoC 컨테이너 : “빈”을 모아둔 통
DI 예제
- 배터리가 있어야 움직이는 장남감들이 있다. → 장난감은 배터리에 의존하고 있다.
- 장난감들에게 배터리를 넣어주는 것 → 의존성 주입
- 배터리 일체형 → 배터리가 떨어지면 장난감을 새로 구입해야 한다.
public class Toy {
Private Battery battery;
public Toy() {
battery = new NormalBattery();
}
}
- Toy 가 NormalBattery에 전적으로 의존되어 있다.
- NormalBattery가 아닌 다른 배터리로 교체하고 싶을 때는 Toy 내부의 코드를 변경해야 한다.
- 만약 Toy1, Toy2, Toy3 여러 Toy 클래스가 있는데, NormalBattery가 아닌 다른 Battery로 교체해야 한다면, 모든 Toy 클래스를 수정해야 한다.
- 배터리 분리형 → 배터리가 떨어지면 배터리만 교체하면 된다.
public class Toy {
Private Battery battery;
public Toy(Battery battery) {
this.battery = battery;
}
}
class Battery {}
class NormalBattery extends Battery {}
class EnergizerBattery extends Battery {}
- Toy 는 필요할 때 Battery 를 외부에서 넘겨받는다.
- Battery 클래스를 상속받은 EnergizerBattery, NormalBattery 도 Toy에 쉽게 전달될 수 있다.
- Toy1, 2, 3 클래스들이 여러 개 있어도, 변경해서 쓸 배터리로 생성된 객체를 전달 받는다면, 배터리가 달라져도 Toy 클래스들은 수정할 필요 없다.
[예제참고]
https://m.blog.naver.com/PostView.nhn?blogId=ljh0326s&logNo=221395815870&proxyReferer=https:%2F%2Fwww.google.com%2F*
DI 장점
- 객체들이 가지는 강한 결합을 느슨하게 만들 수 있다.
- 객체 간의 결합도가 낮아지면, 한 클래스를 수정할 때 다른 클래스를 수정해야 하는 상황을 막을 수 있으므로 유연성이 높아진다.
- 코드의 재사용성이 좋다.
- 코드를 확장하거나 변경할 때 영향을 최소화한다.
IoC(Inversion of Control)
- 객체 관리의 권한이 개발자에서 프레임워크(컨테이너)로 넘어감
- 객체의 생성부터 생명주기 관리까지 컨테이너가 한다.
- 일반적 : 개발자가 자신이 필요한 객체를 생성해서 사용한다.
- 스프링 : 이미 생성된 객체를 용도에 맞게 가져다 사용한다.
- 스프링이 객체(Bean)를 생성해놓고 IoC 컨테이너에 넣어두었다.
- 개발자는 용도에 맞게 이미 생성된 객체를 가져다 사용하면 된다. → 의존성 주입