Spring

[Spring] 빈 (Bean) 설명

오잎 클로버 2022. 1. 31. 10:00
728x90

Spring bean

Bean

Bean은 Spring Framework에서 앱을 구성하는 기본적인 객체입니다.

개발자는 Bean을 정의하고, 활용합니다.

그럼 Container는 개발자가 정의한 Bean을 가지고 객체로 만들고 관리하고, 개발자가 필요로 할때 제공합니다.

즉, Bean을 어떻게 정의하고 사용해야하는 지 개발자는 알고 있어야합니다.

 

@Bean // 해당 어노테이션으로 쉽게 정의할 수 있다.

Bean은 기본 객체이므로 무엇이든지 될 수 있습니다. 다만 Bean은 BeanDefinition으로 정의됩니다.

BeanDefinition에 따라 활용하는 방법이 달라지게 됩니다.

BeanDefinition속성에 따라 Container가 Bean을 어떻게 생성하고 관리할지,

그리고 Bean간의 관계를 어떻게 풀어나갈 것인지를 결정하게 됩니다.

Bean간의 관계를 풀어나간다는 의미는 Bean들 사이에 존재하는 종속성을 해결한다는 뜻입니다.

즉, DI(Dependency Injection)이 작동하도록 Container는 Bean을 생성하고 관리합니다.

 

Bean의 종속성

Container는 개발자를 대신하여 각 Bean이 생성될 때 필요한 객체를 전달합니다. 이를 Dependency Injection이라 합니다. 문제는 종속 관계가 환형, Bean 간에 서로 종속되는 관계를 가질 때 발생합니다.

이때 BeanCurrentlyInCreationException라는 예외를 마주치게 됩니다.

이 예외를 근본적으로 해결하는 방법은 서로에게 종속되지 않도록 관계를 정리해주는 겁니다.

서로에게 종속되는 Bean은 코드 간에 결합을 발생시키는, 클린하지 않은 코드입니다.

다른 해결 방법은 서로 의존하게 되는 타이밍을 다르게 설정하는 방법입니다. 객체가 생성될 때가 아닌 객체의 속성을 설정할 때 종속성을 해결하면 됩니다. 다만 근본적인 문제를 해결하는 방법이 아니기에 추천드리지 않습니다.

 

Bean 생성하는 방법

위 방법처럼 @Bean 어노테이션을 사용하는 방법도 있지만

@Configuration 어노테이션을 사용하는 방법도 있다.

 

Configuration 방식은 Component Scanning을 통해 Bean을 등록하는 방식인데

위 방식이 작동하는 방식은 다소 난해하다

 

Spring IoC Container가 IoC Container를 만들고 그 안에Bean을 등록할때 사용하는Interface들을Life Cycle Callback이라고 부른다.

Life Cycle Callback 중에는 @Component이 붙어있는 모든 Class의 Instance를 생성해 Bean으로 등록하는 작업을 수행하는 Annotation Processor가 등록 돼있다.

Instance : 일반적으로 실행 중인 임의의 프로세스, 해당 클래스의 구조로 컴퓨터 저장공간에서 할당되어 현재 생성된 Object를 의미.

 

이때, @ComonentScan Annotation이 붙어있는 Class가 이에 해당한다.

 

즉, @ComponentScan, @Component Anotation을 사용해서 Bean을 등록하는 방법이다.

 

@ComponentScan은 어느 지점부터 Component를 찾으라고 알려주는 역할을 하고,

@Component는 실제로 찾아서 Bean으로 등록할 Class를 의미한다.

 

@ComponentScan은 @Component이 부여된 Class를 찾아 자동으로 Bean으로 등록해주는 역할을 한다.

@ComponentScan이 붙어있는 Class가 있는 package에서부터 모든 하위 package의 모든 Class를 찾아 다니며,

@Component나 @Component를 사용하는 다른 Annotation을 사용하는 Class를 찾는다.
[EX] Stereotype Annotation(@Controller, @Service, @Repository 등)
Stereotype Annotation들은 내부적으로 @Component Annotation을 사용한다.

 

아래와 같은 방식으로 보통 사용한다.

@Configuration
public class ExampleConfiguration {
    @Bean
    public ExampleController exampleController() {
        return new ExampleController;
    }
}

@Configuration Annotation을 보면 이 Annotation도 내부적으로 @Component를 사용하기 때문 

@ComponentScan의 검색 대상이 되고,
그에 따라 Bean을 정의한 @Configuration이 읽힐때 그 안에 정의한 Bean들이 IoC Container에 등록되는 것이다.

 

어노테이션을 사용하지 않고 XML 파일을 사용하여서도 설정이 가능한데

개인적으로 시도해본적이 없다;;

<!-- A simple bean definition -->
<bean id="..." class="..."></bean>

<!-- A bean definition with scope-->
<bean id="..." class="..." scope="singleton"></bean>

<!-- A bean definition with property -->
<bean id="..." class="...">
	<property name="message" value="Hello World!"/>
</bean>

<!-- A bean definition with initialization method -->
<bean id="..." class="..." init-method="..."></bean>

이렇게 일일이 작성하기 싫기때문이다.

 

또, Spring framework는 기본적으로 Bean을 싱글톤(Singleton)으로 생성 및 관리를 합니다.

 

 

이상입니다.