스프링 빈 설정 메타 정보 - BeanDefinition
스프링은 어떻게 이런 다양한 설정 형식을 지원하는 것일까?
스프링 컨테이너는 왜 어노테이션을 활용한 자바코드(@bean)인지 xml로 빈을 등록한 건지 상관이 없는 걸까?
그 중심에는 BeanDefinition 이라는 추상화가 있다.
쉽게 이야기해서 역할과 구현을 개념적으로 나눈 것이다!
- XML을 읽어서 BeanDefinition을 만들면 된다.
- 자바 코드를 읽어서 BeanDefinition을 만들면 된다.
- 스프링 컨테이너는 자바 코드인지, XML인지 몰라도 된다.
- 추상화(역할)인 BeanDefinition을 사용하기 때문에, 오직 BeanDefinition만 알면 된다.
BeanDefinition 을 빈 설정 메타정보라 한다.
@Bean , 당 각각 하나씩 메타 정보가 생성된다.
스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성한다
- AnnotationConfigApplicationContext 는 AnnotatedBeanDefinitionReader 를 사용해서 AppConfig.class 를 읽고 BeanDefinition 을 생성한다.
- GenericXmlApplicationContext 는 XmlBeanDefinitionReader 를 사용해서 appConfig.xml 설정 정보를 읽고 BeanDefinition 을 생성한다.
- 새로운 형식의 설정 정보가 추가되면, XxxBeanDefinitionReader를 만들어서 BeanDefinition 을 생성하 면 된다.
코드예시
AppConfig가 어노테이션을 활용한 자바코드일 때
테스트코드로 진행
test/beanfind/BeanDefinitonTest.java
public class BeanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 설정 메타정보 확인")
void findApplicationBean() {
// ApplicationContext를 쓰면 getBeanDefinitionNames이 없기 때문에 AnnotationConfigApplicationContext를 써줘야 한다..
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for(String beanDefinitionName : beanDefinitionNames){
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
System.out.println("beanDefinitionName = " + beanDefinitionName +
" // beanDefinition = " + beanDefinition);
}
}
}
}
결과 화면
어노테이션활용한 자바코드로 실행했을 때는 bean에 대한 class 경로가 null인 것을 확인할 수 있다.
어노테이션활용한 자바코드로 실행했을 때는
factoryBeanName=appConfig;
factoryMethodName=memberService 가 명시되어 있다.
appConfing.xml일 때
public class BeanDefinitionTest {
GenericXmlApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
@Test
@DisplayName("빈 설정 메타정보 확인")
void findApplicationBean() {
// ApplicationContext를 쓰면 getBeanDefinitionNames이 없기 때문에 AnnotationConfigApplicationContext를 써줘야 한다..
String[] beanDefinitionNames = ac.getBeanDefinitionNames();
for(String beanDefinitionName : beanDefinitionNames){
BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);
if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {
System.out.println("beanDefinitionName = " + beanDefinitionName +
" // beanDefinition = " + beanDefinition);
}
}
}
}
beanDefinition = Generic bean: class [hello.core.member.MemberServiceImpl]
bean에 대한 class 경로가 구체적으로 명시되어 있다.
xml로 실행했을 때는
factoryBeanName=null; factoryMethodName=null 가 null인 것을 확인 할 수 있다.
defined는 AppConfig로 명시되어 있다.
➕ 참고 ➕
factoryBeanName에는 무슨 차이가 있을까?
빈 등록 방법에는 크게 2가지가 있다.
1. bean을 직접 컨테이너에 올리는 방법(xml사용)
2. Factory Method를 통해서 올리는 방법(@Bean 자바코드 사용)
그렇기 때문에 위에서 appCofing,xml을 사용했을 때는
factoryBeanName=null;
factoryMethodName=null 가 null인 것이다.
'공부 > Spring' 카테고리의 다른 글
[Spring] 싱글톤 패턴 (0) | 2023.11.16 |
---|---|
[Spring] 웹 애플리케이션과 싱글톤 (1) | 2023.11.14 |
[Spring] 다양한 설정 형식 지원 - 자바 코드, XMl (0) | 2023.11.09 |
[Spring] Beanfactory와 ApplicationContext (0) | 2023.11.07 |
[Spring] 스프링 빈 조회 - 상속 관계 (0) | 2023.11.07 |