본 포스팅은
https://chanho0912.tistory.com/8
위 포스팅의 내용을 전반적으로 이해하고 있다고 가정하고 작성하겠습니다.
위 포스팅에서 간략히 IOC container를 다음과 같이 소개하였다.
IOC를 제공하는 Bean들을 담고 있는 Container이다.
조금 더 구체적으로 IOC container가 하는 일을 살펴보면,
* Bean을 생성하고,
* Bean 사이의 의존관계를 설정해주고,
* Bean을 제공해준다.
이렇게 세 가지 정도를 살펴볼 수 있다.
Bean을 일반적으로 Application Context(IOC container)가 생성해주지만, 직접적으로 @Bean 어노테이션을 활용하여 Bean 생성을 해줄 수도 있다.
@Configuration(proxyBeanMethods = false)
@EnableCaching
class CacheConfiguration {
@Bean
public JCacheManagerCustomizer petclinicCacheConfigurationCustomizer() {
return cm -> {
cm.createCache("vets", cacheConfiguration());
};
}
}
다음과 같이 @Bean Annotation을 활용하여 생성해 줄 수도 있지만, 일반적으로 Bean 생성과 관련해서는 우리가 Class에 붙인 Annotation을 따라서 Application Context가 생성해준다.
2, 3 내용은 이전 포스팅에서 설명한 부분과 관련이 깊은데 어떠한 class에서 직접 의존관계를 설정하지 않고(Dependency Injection) IOC container로부터 의존관계를 설정받아 주입받는다.
한번 Application Context에 등록되어 있는 Bean을 조회해 볼 수 없을까?
물론 가능하다.
@Controller
class OwnerController {
private static final String VIEWS_OWNER_CREATE_OR_UPDATE_FORM = "owners/createOrUpdateOwnerForm";
private final OwnerRepository owners;
private VisitRepository visits;
private final ApplicationContext applicationContext;
public OwnerController(OwnerRepository clinicService, VisitRepository visits, ApplicationContext applicationContext) {
this.owners = clinicService;
this.visits = visits;
this.applicationContext = applicationContext;
}
@GetMapping("/bean")
@ResponseBody
public String getBean() {
return applicationContext.getBean(OwnerController.class).toString();
}
...
다음과 같이 ApplicationContext를 class 내부에 주입받아서, getBean이라는 method로 OwnerController를 확인해보자
그러면 다음과 같이 OwnerController가 Bean으로 등록되어 있는 것을 확인해 볼 수 있다.
하지만 직접 Bean으로 등록하는 방법은 될수록 피하는 것이 좋은데, 그 이유는 IOC의 기본 원칙에서 조금 벗어난 방법이기 때문이다.
따라서 상황에 따라 적절히 @Controller, @Service와 같은 어노테이션을 활용하여 IOC container에서 생성해준 Bean을 주입받아 사용하는 것이 더 효율적이라고 할 수 있다.
이번에는 Bean에 대해 자세하게 살펴보자.
Bean이란 Application Context(IOC Container)가 직접 만들어 관리하는 객체를 말한다.
즉
OwnerController ownerController = new OwnerController();
와 같이 생성된 객체는 Bean이 아니고, Spring IOC container에서 생성하여 주입받은 객체만 Bean이라고 할 수 있다.
Bean의 생성과정을 간략히 살펴보면,
SpringBootApplication이 실행될 때 Component Annotation Scan이라는 작업이 시작된다. 즉 @Controller, @Repository와 같이 Component Annotation으로 작성된 class들에 대해 인스턴스를 생성하고, IOC container에 Bean으로 등록하는 일종의 전처리기가 작동하게 된다.
위와 같은 전처리기가 IOC container 생성과 동시에 Bean 생성, 등록을 진행해 주기 때문에 우리는 별도로 객체를 만들 필요 없이 Bean을 주입받을 수 있는 것이다.
*추가로
1. 어떠한 class에서 Bean을 주입받기 위해서는 Bean으로 등록이 되어있어야 한다. 즉 의존성 주입이라는 것은 Bean끼리만 가능하다.
위 Code에서 OwnerController가 OwnerRepository를 주입받을 수 있는 이유는 OwnerRepository가 Bean으로 등록되어 있고, OwnerController가 Bean으로 등록되어 있기 때문에 주입받을 수 있는 것이다.
2. 기본적으로 Spring의 Bean은 싱글톤 스코프로 생성된다.
*싱글톤 스코프란? 하나의 인스턴스만 생성하여 관리하는 것을 말한다.
Controller나 Repository, 혹은 Service와 같은 객체를 보면 이 객체들이 굳이 여러 인스턴스로 참조될 필요가 있을까? 라는 생각을 해 볼 수 있고, 물론 그 답은 x이다. 즉 IOC Container에서 하나의 인스턴스만 생성해서 관리하는 것이 메모리, 성능 면에서 효율적일 것이다. 하지만 일반적으로 Bean으로 등록되지 않는 Entity class와 같은 객체를 보면 하나로 관리하기 어려울 것이다. (이 경우 Prototype scope라는 scope로 매번 다른 인스턴스를 IOC container에서 생성하고 관리하는 방법이 있는데, 다른 포스팅에서 해당 내용을 정리하겠다)
여기까지 이번 포스팅에서 IOC container와 Bean에 대해 살펴보았다.
*저의 글에 대한 피드백이나 지적은 언제나 환영합니다.
'Backend > Spring' 카테고리의 다른 글
[Spring] AOP란? (1) | 2021.06.23 |
---|---|
[Spring/SpringBoot] 코드로 확인하는 Dependency Injection (0) | 2021.06.22 |
[Spring] IOC(Inversion Of Control), DI(Dependency Injection)이란? (0) | 2021.06.16 |
[Spring/SpringMVC] Dispatcher Servlet이란? (1) | 2021.06.15 |
[Spring/SpringBoot] IntelliJ 소개 및 Gradle 프로젝트 설정 (0) | 2021.06.12 |