오봉이와 함께하는 개발 블로그
Spring - 스프링 컨테이너와 빈 - 5(스프링 빈 설정 메타 정보 - BeanDefinition) 본문
728x90
스프링 빈 설정 메타 정보 - BeanDefinition
- xml, java, groovy 등 다양한 설정 형식을 지원할 수 있는 이유는 BeanDefinition이라는 추상화가 있기 때문.
- 쉽게 표현하면 역할과 구현을 개념적으로 나눈 것
- BeanDefinition은 읽어서 만들기만 하면 된다.
- XML을 읽어서 BeanDefinition을 만든다.
- 자바 코드를 읽어 BeanDefinition을 만든다.
- 스프링 컨테이너는 자바든 XML이든 BeanDefinition만 알면 된다.
- BeanDefinition을 빈 설정 메타정보라 함.
- @Bean, <bean>당 각각 하나씩 메타 정보가 생성됨.
- 스프링 컨테이너는 메타정보를 기반으로 스프링 빈을 생성함.
코드 레벨로 더 깊게 들어가자
- AnnotationConfigApplicationContext는 AnnotatedBeanDefinitionReader를 사용해서 AppConfig.class를 읽고 BeanDefinition을 생성함
- GenericXmlApplicationContext는 XmlBeanDefinitionReader를 사용해서 appConfig.xml 설정 정보를 읽고 BeanDefinition을 생성함.
위와 같이 새로운 형식의 설정 정보가 추가되면 XXXBeanDefinitionReader를 만들어 BeanDefinition을 생성하면 됨
BeanDefinition 살펴보기
BeanDefinition 정보
코드
package hello.core.beandefinition;
import hello.core.AppConfig;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
public class BeanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
// GenericXmlApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
@Test
@DisplayName("빈 메타정보 확인")
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
+ " beanDefinition = " + beanDefinition);
}
}
}
}
출력
beanDefinitionName = appConfig beanDefinition = Generic bean: class [hello.core.AppConfig$$EnhancerBySpringCGLIB$$713455cd]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null
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
beanDefinitionName = orderService beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=orderService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
beanDefinitionName = discountPolicy beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=discountPolicy; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig
- BeanClassName
- 생성할 빈의 클래스 명
- 자바 설정 처럼 팩토리 역할의 빈을 사용하면 없다.
- factoryBeanName
- 팩토리 역할의 빈을 사용할 경우 이름 (예 : appConfig)
- xml을 사용할 때
- factoryMethodName
- 빈을 생성할 팩토리 메소드 지정 (예 : memberService)
- Java 코드를 사용할 때
- Scope
- 싱글톤(기본값)
- lazyInit
- 스프링 컨테이너를 생성할 때 빈을 생성하는 것이 아닌, 실제 빈을 사용할 때 까지 최대한 생성을 지연처리 하는지에 대한 여부
- InitMethodName
- 빈을 생성하고, 의존관계를 적용한 뒤 호출되는 초기화 메소드 명
- DestroyMethodName
- 빈의 생성 주기가 끝나 제거하기 직전에 호출되는 메소드 명
- Constructor arguments, Properties
- DI에서 사용
- 자바 설정 처럼 팩토리 역할의 빈을 사용하면 없다.
정리
- BeanDefinition을 직접 생성해서 스프링 컨테이너를 등록할 수 있지만, 실무에서 직접 정의하거나 사용할 일은 거의 없다.
- 고로 어려우면 그냥 넘어가도 됨.....
- BeanDefinition에 대해서 너무 깊이있게 이해하기 보단, 스프링이 다양한 형태의 설정 정보를 BeanDefinition으로 추상화해서 사용하는 것 정도만 이해하면 됨.
- 가끔 스프링 코드나 스프링 관련 오픈 소스의 코드를 볼 때, BeanDefinition이 보일 때가 있으면 위 케머니즘을 떠올리면 됨.
AnnotationConfigApplicationContext와 GenericXmlApplicationContext
- 둘이 출력 정보가 다르다.
- 스프링에 빈을 등록하는 방법은 여러가지가 있는데, 크게 두 가지로 보면 직접 스프링 빈을 등록하는 방법(xml)과 우회해서 등록하는 FactoryMethod(AppConfig.class : 자바 코드를 사용)라는 방법이 있다.
- FactoryMethod는 외부에서 메소드를 호출하여 생성하는 방식이다.
출처 : 인프런 김영한 지식공유자님의 스프링 완전 정복 로드맵 강의
728x90
'BE > Spring' 카테고리의 다른 글
Spring - 싱글톤 컨테이너(싱글톤 컨테이너, 싱글톤 방식의 주의점) (0) | 2022.06.08 |
---|---|
Spring - 싱글톤 컨테이너(웹 애플리케이션과 싱글톤, 싱글톤 패턴) (0) | 2022.06.07 |
Spring - 스프링 컨테이너와 빈 - 4(BeanFactory와 ApplicationContext, XML 기반 appConfig) (0) | 2022.06.06 |
Spring - 스프링 컨테이너와 빈 - 3(스프링 빈 조회 - 상속관계) (0) | 2022.06.06 |
Spring - 스프링 컨테이너와 빈 - 2(스프링 빈 조회 기본, 동일한 타입 둘 이상) (0) | 2022.06.06 |
Comments