Carefree Hub

Command Palette

Search for a command to run...

Spring Configuration - 설정 정보 구성

Spring Configuration - 설정 정보 구성

Java 클래스와 XML을 사용한 스프링 설정 방법과 BeanDefinition 이해하기

Carefreelife98
3분 소요

다양한 설정 형식(Configuration) 지원 - 자바코드 및 XML

스프링 컨테이너는 다양한 형식의 설정 정보를 사용할 수 있도록 유연하게 설계되어 있다.

  • Java
  • XML
  • Groovy

설정 형식

  • AnnotationConfigApplicationContext: Java의 설정 클래스를 사용하여 스프링의 설정 정보를 구성
  • GenericXmlApplicationContext: XML 파일을 사용하여 스프링의 설정 정보를 구성
  • ~ ApplicationContext: 사용자가 Customizing한 파일로 스프링의 설정 정보를 구성할 수도 있다

Annotation 기반 Java 클래스를 활용한 설정 사용하기

java
1// AppConfig.class 라는 설정 클래스를 통해 설정 정보 구성
2AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class)
  • AnnotationConfigApplicationContext를 사용하여 설정 클래스를 파라미터로 넘겨주면 된다

XML 설정 사용

근래에는 스프링 부트를 많이 사용하면서 XML 기반 설정 정보 구성 방식은 잘 사용하지 않는다. 하지만 어느정도 규모 및 연차가 있는 회사에 취업한다면, 대부분 XML 설정을 사용하고 있을 것이다.

java
1GenericXmlApplicationContext xac = new GenericXmlApplicationContext("classpath:applicationContext.xml")
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

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

AnnotationConfigApplicationContext - AnnotatedBeanDefinitionReader

AnnotatedBeanDefinitionReader

AnnotationConfigApplicationContext 내부

AnnotationConfigApplicationContext를 타고 들어가보면 AnnotatedBeanDefinitionReader 가 존재하는 것을 볼 수 있다.

  • AnnotatedBeanDefinitionReader: 스프링 설정 정보(Java-Class)를 읽어 적절한 BeanDefinition을 생성하는 역할

GenericXmlApplicationContext 내부

GenericXmlApplicationContext에도 마찬가지로 XmlBeanDefinitionReader를 가지고 있다.

  • XmlBeanDefinitionReader: 스프링 설정 정보(.xml)을 읽어 적절한 BeanDefinition을 생성하는 역할

새로운 형식의 설정 정보가 추가되면, ~BeanDefinitionReader를 만들어 BeanDefinition을 생성하면 된다.

BeanDefinition 출력해보기

java
1public class BeanDefinitionTest {
2
3 AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
4
5 @Test
6 @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}

출력 결과

bash
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=null
2beanDefinitionName = appConfig
3
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.AppConfig
5beanDefinitionName = memberService
6
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.AppConfig
8beanDefinitionName = memberRepository

beanDefinition을 출력해보면, 해당 빈의 속성을 볼 수 있다:

  • scope
  • 추상 클래스
  • 지연 초기화
  • autowire
  • ...

참고: Inflearn - 김영한님 강의(스프링 핵심 원리 기본편)