Spring의 특징은 DI(의존성 주입) 패턴을 사용하여 IoC(제어의 역전) 설계 원칙을 구현한다는 점이다.
이게 도.대.체. 무엇인지 알아보자..!
객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식
쉽게 말하자면 하나의 코드가 다른 코드를 필요로 하는 정도
public class Consumer {
void eat() {
Chicken chicken = new Chicken();
chicken.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.eat();
}
}
class Chicken {
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
만약 Consumer 가 치킨이 아니라 피자를 먹고 싶어 한다면? 많은 수의 코드 변경이 불가피함
이 경우 Consumer 와 Chicken는 강한 결합, 강한 의존성이라고 할 수 있음
Java의 Interface를 활용하면 결합을 느슨하게 할 수 있음
public class Consumer {
void eat(Food food) {
food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.eat(new Chicken());
consumer.eat(new Pizza());
}
}
interface Food {
void eat();
}
class Chicken implements Food{
@Override
public void eat() {
System.out.println("치킨을 먹는다.");
}
}
class Pizza implements Food{
@Override
public void eat() {
System.out.println("피자를 먹는다.");
}
}
public class Consumer {
Food food; // 인터페이스 필드
void eat() {
this.food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.food = new Chicken(); // 필드에 직접 주입
consumer.eat();
consumer.food = new Pizza(); // 필드에 직접 주입
consumer.eat();
}
}
public class Consumer {
Food food; // 인터페이스 필드
void eat() {
this.food.eat();
}
public void setFood(Food food) {
this.food = food;
}
public static void main(String[] args) {
Consumer consumer = new Consumer();
consumer.setFood(new Chicken()); // 메소드로 주입
consumer.eat();
consumer.setFood(new Pizza()); // 메소드로 주입
consumer.eat();
}
}
객체의 불변성을 지켜줄 수 있기 때문에 가장 많이 쓰는 방법
public class Consumer {
Food food; // 인터페이스 필드
public Consumer(Food food) { // 인터페이스 필드를 인자로 둔 생성자
this.food = food;
}
void eat() {
this.food.eat();
}
public static void main(String[] args) {
Consumer consumer = new Consumer(new Chicken()); // 생성자로 주입
consumer.eat();
consumer = new Consumer(new Pizza()); // 생성자로 주입
consumer.eat();
}
}
메소드나 객체의 호출작업을 개발자가 결정하는 것이 아니라, 외부에서 결정되는 것
IoC는 제어의 역전이라고 말하며, 간단히 말해 "제어의 흐름을 바꾼다"라고 한다.