보통 일반적인 정의
자바 및 Spring에서 말하는 의존성
-> 하나의 객체 내에서 필요에 의해 다른 객체를 사용하는 경우
Class Computer{
Cpu cpu = new Cpu
public Computer(){
cpu.run();
}
}
이 때 Computer 클래스는 항상 cpu 객체를 생성한다.
또한 Computer는 항상 cpu의 메서드를 사용하므로Computer
는 Cpu
에 의존한다 볼 수 있다
-> 이 경우 run함수를 수정할 경우 부득이하게 Computer 생성자 결과 또한 바뀌므로 결합력(높은 의존성)이 높아
유지보수 어려움
-> 또 다른 객체를 사용하고자 하면 수정에 번거로움이 생김
DI
는 하나의 객체 내에서 필요한 다른 객체를 생성자
또는 Setter
를 통해 주입하는 것
class Computer{
Cpu cpu
public Computer(Cpu cpu){
this.cpu = cpu;
cpu.run();
}
}
Cpu cpu = new Cpu();
Computer computer = new Computer(cpu);
이전과 다르게 cpu변수를 인자로 받아 내부의 cpu 변수에 옮겨담음(주입)
이 후 함수명은 run으로 같지만 이전과 다른 기능을 동작시키고 싶으면 Cpu 클래스를 상속받은 다른 클래스
의 객체를 생성자를 통해 집어 넣으면 됨!!
DI의 대표적인 기능 -> @Autowired
Spring Framework에서는 인터페이스와 인터페이스를 상속받은 클래스 중 인터페이스를 가지고 Controller와 Service를 동작시킴
객체를 참조할때는 그 인터페이스를 사용하는 것이 바람직
-> 결합도가 느슨해져 프로그램 개발이 유연
반드시 하나 이상의 클래스에서 인터페이스를 구현(재정의) 해야 한다
결과적으로 @AutoWired를 통해 인터페이스를 선언한 변수에 자동적으로 그 인터페이스를 재정의한 객체를 주입시킨다는 것이 핵심
private Car car;
-> car이라는 변수에 Car 인터페이스를 재정의한 클래스 객체 CarImpl를 주입시킨다는 것!
private Car car = new CarImpl
List<int> list = new ArrayList<int>();
하지만 반드시 하나의 클래스만 해당 인터페이스를 재정의
해야 한다는 조건이 있다
두개 이상의 클래스로 하나의 인터페이스 구현시 @Qualifier
또는 @Resource
로 여러개의 재정의한 클래스 중 특정 Bean의 이름에 맞는 클래스 객체를 가져오게 해야함
일반적 자바 코드에서의 객체 사용법
@RestController
public class NoDiController{
private MyService myservice = new MyServiceImpl();
@GetMapping("no-di/hello")
public String getHello(){
return service.getHello();
}
}
의존성 주입 : 생성자를 통한 의존성 주입
@RestController
public class DiController{
MyService myService;
@AutoWired
public DIController(Myservice myService){
this.myService = myService;
}
@GetMapping("/di/hello")
public String getHello()[
return myService.gethello();
}
}
의존성 주입 : 필드 객체 선언을 통한 의존성 주입
@RestController
public class FieldInjectionController{
@Autowired
private MyService myService;
}
의존성 주입 : Setter메서드를 통한 주입
@RestController
public class SetterDiInjectionController{
MyService myService;
@AutoWired
public void SetMyService(MyService myService){
this.myService = myService;
}
}