
Spring Configuration - 설정 정보 구성
Java 클래스와 XML을 사용한 스프링 설정 방법과 BeanDefinition 이해하기
다양한 설정 형식(Configuration) 지원 - 자바코드 및 XML
스프링 컨테이너는 다양한 형식의 설정 정보를 사용할 수 있도록 유연하게 설계되어 있다.
- Java
- XML
- Groovy

- AnnotationConfigApplicationContext: Java의 설정 클래스를 사용하여 스프링의 설정 정보를 구성
- GenericXmlApplicationContext: XML 파일을 사용하여 스프링의 설정 정보를 구성
- ~ ApplicationContext: 사용자가 Customizing한 파일로 스프링의 설정 정보를 구성할 수도 있다
Annotation 기반 Java 클래스를 활용한 설정 사용하기
1// AppConfig.class 라는 설정 클래스를 통해 설정 정보 구성2AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class)AnnotationConfigApplicationContext를 사용하여 설정 클래스를 파라미터로 넘겨주면 된다
XML 설정 사용
근래에는 스프링 부트를 많이 사용하면서 XML 기반 설정 정보 구성 방식은 잘 사용하지 않는다. 하지만 어느정도 규모 및 연차가 있는 회사에 취업한다면, 대부분 XML 설정을 사용하고 있을 것이다.
1GenericXmlApplicationContext xac = new GenericXmlApplicationContext("classpath:applicationContext.xml")1<?xml version="1.0" encoding="UTF-8"?>2<beans xmlns="http://www.springframework.org/schema/beans"3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">5
6 <bean id="memberService" class="hello.core.member.MemberServiceImpl">7 <constructor-arg name="memberRepository" ref="memberRepository"/>8 </bean>9
10 <bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"/>11
12 <bean id="orderService" class="hello.core.order.OrderServiceImpl">13 <constructor-arg name="memberRepository" ref="memberRepository"/>14 <constructor-arg name="discountPolicy" ref="discountPolicy"/>15 </bean>16
17 <bean id="discountPolicy" class="hello.core.discount.RateDiscountPolicy"/>18
19</beans><bean>태그를 사용하여 스프링 빈을 등록- Java 설정 클래스를 사용할 때와 비슷하게 1:1 매핑되는 것을 볼 수 있다
스프링 빈 설정 메타 정보 - BeanDefinition

- 스프링은
BeanDefinition을 통한 추상화로서 다양한 설정 형식을 지원한다- 추상화: 역할과 구현을 개념적으로 나눈 것
- XML을 읽어서 BeanDefinition을 생성
- Java 코드를 읽어서 BeanDefinition을 생성
- 스프링 컨테이너는 설정 정보가 어떤 형식으로 정의되어 있는지 알 필요 없이, BeanDefinition만 알고 있으면 된다
- 추상화: 역할과 구현을 개념적으로 나눈 것
BeanDefinition: 빈 설정 메타정보@Bean,<bean>당 각각 하나씩 메타 정보 생성
- 스프링 컨테이너는 이 메타 정보를 기반으로 스프링 빈을 생성
AnnotationConfigApplicationContext - AnnotatedBeanDefinitionReader


AnnotationConfigApplicationContext를 타고 들어가보면 AnnotatedBeanDefinitionReader 가 존재하는 것을 볼 수 있다.
AnnotatedBeanDefinitionReader: 스프링 설정 정보(Java-Class)를 읽어 적절한 BeanDefinition을 생성하는 역할

GenericXmlApplicationContext에도 마찬가지로 XmlBeanDefinitionReader를 가지고 있다.
XmlBeanDefinitionReader: 스프링 설정 정보(.xml)을 읽어 적절한 BeanDefinition을 생성하는 역할
새로운 형식의 설정 정보가 추가되면, ~BeanDefinitionReader를 만들어 BeanDefinition을 생성하면 된다.
BeanDefinition 출력해보기
1public class BeanDefinitionTest {2
3 AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);4
5 @Test6 @DisplayName("빈 설정 메타정보 확인")7 void AnnotationConfigBeanDefinitionTest() {8 String[] beanDefinitionNames = ac.getBeanDefinitionNames();9 for (String beanDefinitionName : beanDefinitionNames) {10 BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionName);11
12 if (beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION) {13 System.out.println("beanDefinition = " + beanDefinition + " beanDefinitionName = " + beanDefinitionName);14 }15 }16 }17}출력 결과
1beanDefinition = Generic bean: class [hello.core.AppConfig$$SpringCGLIB$$0]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null2beanDefinitionName = appConfig3
4beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in hello.core.AppConfig5beanDefinitionName = memberService6
7beanDefinition = Root bean: class [hello.core.AppConfig]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=memberRepository; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in hello.core.AppConfig8beanDefinitionName = memberRepositorybeanDefinition을 출력해보면, 해당 빈의 속성을 볼 수 있다:
- scope
- 추상 클래스
- 지연 초기화
- autowire
- ...