IoC와 DI, 그리고 Bean

IoC란

public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService() {
        this.orderRepository = new MemoryOrderRepository();
    }
}

DI란

public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService() {
        this.orderRepository = new MemoryOrderRepository();
    }
}

스프링 컨테이너의 빈 생성과 주입 과정

  1. POJO 형태로 클래스 작성
  2. 빈 등록 대상과 의존 관계 정보를 스프링에게 전달
  3. 스프링 컨테이너가 이 정보를 바탕으로 빈을 생성
  4. 생성하는 과정에서 필요한 의존 관계를 주입
  5. 이후 생성된 빈은 컨테이너가 관리

DI 방식

설정 방식에 따른 DI

명시적 DI

@Configuration
public class AppConfig {

    @Bean
    public OrderRepository orderRepository() {
        return new MemoryOrderRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderService(orderRepository());
    }
}

@Configuration
public class AppConfig {

    @Bean
    public OrderRepository orderRepository() {
        return new MemoryOrderRepository();
    }

    @Bean
    public OrderService orderService() {
        return new OrderService(orderRepository());
    }
}

묵시적 DI


생성자 주입

@Component
public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

세터 주입

@Component
public class OrderService {

    private OrderRepository orderRepository;

    @Autowired
    public void setOrderRepository(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

필드 주입

@Component
public class OrderService {

    @Autowired
    private OrderRepository orderRepository;
}

세터 주입과 필드 주입은 객체가 생성된 뒤 의존성을 주입하는 방식 자바의 final 필드는 객체 생성이 끝나기 전에 초기화되어야 하므로, 세터 주입이나 필드 주입에서는 의존성 필드를 final로 둘 수 없음

@Autowired란

@Component
public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}
@Component
public class OrderService {

    private final OrderRepository orderRepository;
    private final DiscountPolicy discountPolicy;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
        this.discountPolicy = null;
    }

    @Autowired
    public OrderService(
        OrderRepository orderRepository,
        DiscountPolicy discountPolicy
    ) {
        this.orderRepository = orderRepository;
        this.discountPolicy = discountPolicy;
    }
}

@Primary

@Primary
@Component
public class MemoryOrderRepository implements OrderRepository { ... }

@Component
public class JdbcOrderRepository implements OrderRepository { ... }
@Component
public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }
}

@Qualifier

@Component
@Qualifier("memoryRepo")
public class MemoryOrderRepository implements OrderRepository { ... }

@Component
@Qualifier("jdbcRepo")
public class JdbcOrderRepository implements OrderRepository { ... }
@Component
public class OrderService {

    private final OrderRepository orderRepository;

    public OrderService(
        @Qualifier("jdbcRepo") OrderRepository orderRepository
    ) {
        this.orderRepository = orderRepository;
    }
}

댓글