본문 바로가기

카테고리 없음

빈(Bean)과 스프링 IoC 컨테이너

그런데 DI 를 사용하기 위해서는 객체 생성이 우선 되어야 했습니다. 과연 어디서 객체 생성을 해야 할까요? 바로 스프링 프레임워크가 필요한 객체를 생성하여 관리하는 역할을 대신해 줍니다.

 

  • 빈 (Bean): 스프링이 관리하는 객체
  • 스프링 IoC 컨테이너: '빈'을 모아둔 통
  • IOC: 제어의 역전

 

빈을 등록하는 2가지 방법


스프링 '빈' 등록 방법은 2가지가 있습니다.

1. @Component 어노테이션을 클래스 위에 설정

@Component
public class ProductService { ... }

 

이렇게 빈으로 등록할 클래스 위에 Component annotation만 달아놓으면

해당 클래스의 객체를 직접 생성 할 것입니다.

 

ProductService productService = new ProductService();

 

생성된 객체는 스프링 IoC 컨테이너에서 빈 (productService)으로 저장 될 것입니다.

이제 필요할 때마다 스프링 IoC에 존재하는 빈을 꺼내서 사용할 수 있기에 DI가 가능해집니다.

어떻게 스프링이 @Component 있는 클래스를 확인하고 bean으로 할까?

@Component를 찾는 역할을 하는 것이 @ComponentScan 어노테이션의 역할입니다.

ComponenetScan 어노테이션은 main 클래스에 달려있는 SpringBootApplication 어노테이션을 따라 들어가면 확인할 수 있습니다.

2. 컨피그를 이용하여 직접 등록

스프링 '빈' 등록 방법은 두가지가 있다고 했었는데

남은 한가지는 무엇일까요??

 

바로 Config를 이용해서 직접 '빈'으로 등록하는 방법입니다.

아래와 같이 Bean 어노테이션을 직접 달아주시면 됩니다.

 

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class BeanConfiguration {

    @Bean
    public ProductRepository productRepository() {
        String dbUrl = "jdbc:h2:mem:springcoredb";
        String dbId = "sa";
        String dbPassword = "";

        return new ProductRepository(dbUrl, dbId, dbPassword);
    }
}

 

자! 그럼 이제 '빈' 등록을 완료하였으니 사용하는 방법을 알아보도록 하겠습니다.

 

1. '빈'을 사용할 멤버 변수 위에 Autowired 어노테이션을 이용

 

@Component
public class ProductService {
		
    @Autowired
    private ProductRepository productRepository;
		
		// ...
}

 

2. '빈'을 사용할 클래스 위에 Autowired 어노테이션을 이용

 

@Component
public class ProductService {

    private final ProductRepository productRepository;

    @Autowired
    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }
		
		// ...
}

 

Autowired 어노테이션은 생성자가 한개만 있을 때는 생략이 가능합니다 (Spring 4.3 버전 이후)

스프링 IoC 컨테이너에 의해 관리되는 클래스에서만 사용이 가능합니다.

 

3. Lombok의 RequiredArgsConstructor 어노테이션 사용

대신 멤버 변수에는 final 키워드를 달고 있어야 합니다.

 

@RequiredArgsConstructor // final로 선언된 멤버 변수를 자동으로 생성합니다.
@RestController // JSON으로 데이터를 주고받음을 선언합니다.
public class ProductController {

    private final ProductService productService;
    
    // 생략 가능
		// @Autowired
		// public ProductController(ProductService productService) {
		//     this.productService = productService;
		// }
}