제어의 역전(IOC, Inversion Of Control)
제어의 역전이란 메소드나 객체의 호출작업을 개발자가 결정하는게 아닌 외부에서 결정되는 것을 의미한다.
쉽게 말해 객체의 제어권을 IOC 컨테이너에게 넘겨주어 객체의 생성부터 생명주기의 관리까지 객체에 대한
제어권이 바뀐것을 IOC라고 한다.
IOC를 사용하지 않는 경우 - new 방식을 써서 객체를 필요할때마다 생성한다.
//Test 객체
class Test{
String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
//main
public static void main(String[] args){
//IOC 컨테이너에게 맡기지 않고 개발자가 직접 new 키워드를 사용하여 생성
Test test = new Test();
}
IOC를 사용하는경우 - new 방식을 써서 객체를 생성할 필요가 없다.
//Test 객체
@Bean
class Test{
String name;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
}
//main
public static void main(String[] args){
//필요없음
}
@Bean 어노테이션을 사용하여 컨테이너에게 이 객체는 너가 관리해야 하는 객체라는걸 미리 알려준다.
* IOC 컨테이너 특징
1. IOC 컨테이너는 객체의 생성을 책임지고, 의존성을 관리한다.
2. POJO의 생성, 초기화, 서비스, 소멸에 대한 권한을 가진다.
3. 개발자들이 직접 POJO를 생성할 수 있지만, 컨테이너에게 맡긴다.
* POJO(Plain Old Java Object, 단순한 자바 오브젝트)
객체지향적인 원리에 충실하면서 환경과 기술에 종속되어 동작하는것이 아닌 순수한 자바 객체를 의미한다.
1. 특정 규약에 종속되지 않는다.
자바 언어와 꼭 필요한 API 외에 종속되지 않는다.
2. 특정 환경에 종속되지 않는다.
특정 프레임워크나 서버에서만 동작가능한 코드라면 POJO라 할 수 없다. POJO는 환경에 독립적이여야한다.
3. 객체지향원리에 충실해야 한다.
DI(Dependency Injection, 의존성 주입)
DI란 의존성 주입이라고 하며, 객체를 직접 생성하는게 아니라 외부에서 객체를 생성한 후 주입 시켜주는 방식이다.
위 그림의 A 클래스와 B클래스가 존재한다.
왼쪽은 A Class에서 B Class(객체)를 new 생성자를 통해서 직접 생성하는 방법이고,
오른쪽은 외부에서 B 객체를 생성한 후 setter()를 통해 사용하는 방법이다.
* 의존성 주입을 사용하는 이유
A Class에서 B Class를 사용하기 위해 선언하면 A Class는 B Class에 의존성을 가진다고 한다. 여기서 B Class의 내용을 수정했을경우 A Class에서 생성한 B Class도 수정해야하는 문제가 발생한다. 즉, 결합도가 높아진다.
의존성 주입을 했을경우
1. 객체간의 의존성을 줄이거나 없앨 수 있다.
2. 객체간의 결합도를 줄이면서 코드의 유연성이 증가한다.
예)
//Test 객체
class Test{
String name;
Obo obo;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setObo(Obo obo){
this.obo = obo;
}
}
//Obo 객체
class Obo{
String number;
public void setNumber(String number){
this.number= number;
}
public String getNumber(){
return number;
}
}
//main
public static void main(String[] args){
//IOC 컨테이너에게 맡기지 않고 개발자가 직접 new 키워드를 사용하여 생성
Test test = new Test();
Obo other_obo = new Obo();
test.setObo(other_obo);
}
위 코드를 보면 Test 객체 안에 Obo 객체가 들어가 있다.
여기서 Test 객체는 Obo 객체에게 "의존성을 가진다"
그리고 test.setObo(other_obo) 를 통해 test의 Obo 객체에 other_obo 객체를 집어 넣는건
"의존성 주입"이라고 한다.
위와 같은 의존성 주입을 @Autowired 어노테이션을 사용하여 Spring에서 알아서 해준다.
예)
//Test 객체
@Bean
class Test{
String name;
// 빈으로 등록되어 있는 Obo 객체를 컨테이너에서 찾아 자동으로 주입해준다.
@Autowired
Obo obo;
public void setName(String name){
this.name = name;
}
public String getName(){
return name;
}
public void setObo(Obo obo){
this.obo = obo;
}
}
//Obo 객체
@Bean
class Obo{
String number;
public void setNumber(String number){
this.number= number;
}
public String getNumber(){
return number;
}
}
//main
public static void main(String[] args){
//필요없음
}
@Autowired를 사용했으므로, @Bean을 사용해 컨테이너에 등록되어 있는 객체 Obo를 찾아서 알아서 주입해준다.