BeanDefinition이란?
- 단어 그대로 스프링
빈의 설정 메타 정보
이다. - 각 @Bean,
당 각 하나씩 메타 정보가 생성된다. - 스프링 컨테이너는 이 메타 정보를 기반으로 스프링 빈을 생성한다.
어떻게 다양한 설정 방식을 지원 할까?
- 해당 글에서 빈 설정 방식을 자바 코드, xml 등 방식을 지원하는데 이게 가능한 이유가
BeanDefinition이라는 추상화
가 있기 때문이다. - BeanDefinition은
역할(interface)가 되는 것이고
, AppConfig.class, appConfig.xml, appConfig.xxx 등과 같은 것들이구현
이 되는 것이다. 결국 스프링 컨테이너는 BeanDefinition만 바라 보기 때문에 가능한 것이다.
구조를 그림으로 보면 아래와 같다.
조금 더 상세하게 들어가 보자.
스프링 컨테이너(ApplicationContext)는 BeanDefinition만 보고 설정 방식을 지원한다고 했다.
어떤 구조로 되어 있는지 코드 레벨에서 살펴 보도록 하자.
크게 설정 정보에는 자바 설정 구현체인 AnnotationConfigApplicationContext
와 xml 설정 구현체인 GenericXmlApplicationContext
이 있다.
AnnotationConfigApplicationContext 코드를 보면 인스턴스 변수가 AnnotatedBeanDefinitionReader
이다.
AnnotatedBeanDefinitionReader는 AppConfig.class를 읽어 BeanDefinition을 생성한다.
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {
private final AnnotatedBeanDefinitionReader reader;
....
GenericXmlApplicationContext을 코드를 보면 인스턴스 변수가 XmlBeanDefinitionReader
이다.
XmlBeanDefinitionReader도 동일하게 appConfig.xml을 읽어 BeanDefinition을 생성하게 된다.
public class GenericXmlApplicationContext extends GenericApplicationContext {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
...
BeanDefinition 메타 정보 로그 확인
실제로 BeanDefinition의 메타 정보가 어떻게 되어있는지 대략적으로만 보도록 하자.
아래와 같이 메타 정보를 확인 할 수 있다.
class BeanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@DisplayName("빈 설정 메타정보 확인")
@Test
void findApplicationBean() {
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
System.out.println("beanDefinitionName = " + beanDefinitionName);
System.out.println("beanDefinition = " + beanDefinition);
}
}
}
아래에 자바 코드로 등록한 빈의 메타 정보를 확인 해보도록 하겠다.
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
}
로그는 이처럼 나오는데 이런게 있다는 정도만 알면 된다. 딱 2개만 살펴보자.
factoryBeanName → AppConfig의 명이 되고, factoryMethodName → 빈의 명이 된다.
BeanDefinition은 이런 식으로 여러 메타 정보를 가진다.
beanDefinitionName = memberService
beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false;
factoryBeanName=appConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionName = memberRepository
beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false;
factoryBeanName=appConfig; factoryMethodName=memberRepository; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
정리
- 스프링은 다양한 설정 정보를 지원하는데 BeanDefinition이라는 빈의 메타 정보를 추상화하는 것으로 가능하게 한다.
'Spring' 카테고리의 다른 글
스프링의 @ComponentScan (0) | 2022.01.14 |
---|---|
스프링의 @Configuration과 싱글톤의 관계 (0) | 2022.01.14 |
스프링의 자바 코드와 XML 설정 방식 (0) | 2022.01.14 |
스프링의 자바 코드와 XML 설정 방식 (0) | 2022.01.10 |
스프링의 BeanFactory와 ApplicationContext의 차이 (0) | 2022.01.10 |