IoC(Inversion of Control) 제어의 역전

개발자가 직접 객체의 생성과 소멸 객체간 관계같은 객체의 제어를 수행하는 것이 아니라, 여러 프레임워크, 컨테이너에서 제어를 수행하는 것

 

 

DI(Dependency Injection) 의존성 주입

객체를 직접 생성하지 않고 외부에서 미리 만든 객체를 주입하는 것 → 클래스 간 결합을 느슨하게 해서 어떤 클래스의 변경이 그 클래스를 이용하는 다른 클래스에 미치는 영향을 줄인다.

 

  • ⭐️⭐️⭐️생성자를 통한 주입(거의 이거 씀)

Consumer consumer = new Consumer(new Chicken()); 와 같이 생성자를 통해 주입

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();
    }
}

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("피자를 먹는다.");
    }
}

 

 

 

  • 메서드를 통한 주입

consumer.setFood(new Chicken()); 와 같이 setFood 메서드로 주입

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();
    }
}

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("피자를 먹는다.");
    }
}

 

 

  • 필드에 직접 주입(잘 안 씀)

consumer.food = new Chicken();

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();
    }
}

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("피자를 먹는다.");
    }
}

 

 

  • +) Lombok 사용

클래스 위에 @RequiredArgsConstructor를 달고 멤버 변수에 final을 달아준다.

@Component
@RequiredArgsConstructor // final로 선언된 멤버 변수를 파라미터로 사용하여 생성자를 자동으로 생성합니다.
public class MemoService {
    private final MemoRepository memoRepository;
}

 

 

 

 

IoC Container 

bean들을 모아둔 하나의 컨테이너

 

 

Bean

스프링이 관리하고 있는 객체, 이름은 클래스 명에서 첫 글자를 소문자로 바꾼 것으로 결정된다.

  • 클래스 위에 @Component를 달면 bean으로 등록된다.

3 Layer Annotation

Controller, Service, Repository의 역할로 구분된 클래스들은 @Component 대신 각각

  1. @Controller, @RestController
  2. @Service
  3. @Repository

를 달아주면 된다.

 

  • 객체의 의존성을 가지는 부분(객체를 주입 받는 부분)에 @Autowired를 달아준다. 생성자가 1개일 땐 생략 가능하다.
@RestController
@RequestMapping("/api")
public class MemoController {

    private final MemoService memoService;

    @Autowired
    public MemoController(MemoService memoService) {
        this.memoService = memoService;
    }
    
    ....
}

위 코드에서 생성자는 MemoController(MemoService memoService) 하나이므로 @Autowired를 생략해도 된다.

 

 

 

 

 

'TIL > WEEK5' 카테고리의 다른 글

SpringBoot의 JPA  (0) 2023.06.15
1주차 숙제  (0) 2023.06.13
Spring 입문 1주차  (0) 2023.06.12

+ Recent posts