Spring

[Spring] 빈 설정 형식(xml) / 빈 설정 메타 정보 (BeanDefinition)

최MAX 2022. 3. 26. 23:51

XML 설정 사용

 최근에는 많이 사용하지 않지만, 알아두는 것이 좋겠다.

 

GenericXmlApplicationContext를 사용하면서 xml 설정 파일을 넘기면 된다.

 

XmlAppConfig 사용 자바 코드

 

test 밑 XmlAppContext에서 테스트 실행

public class XmlAppContext {
    @Test
    void xmlAppContext() {
        ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        Assertions.assertThat(memberService).isInstanceOf(MemberService.class);
    }
}

실행 결과

당연히 오류

main의 resources에 아래와 같이 appConfig.xml 파일 생성

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="memberService" class="hello.core.member.MemberServiceImpl">
        <constructor-arg name="memberRepository" ref="memberRepository" />
    </bean>
    <bean id="memberRepository" class="hello.core.member.MemoryMemberRepository"/>
    <bean id="orderService" class="hello.core.order.OrderServiceImpl">
        <constructor-arg name="memberRepository" ref="memberRepository" />
        <constructor-arg name="discountPolicy" ref="discountPolicy" />
    </bean>
    <bean id="discountPolicy" class="hello.core.discount.RateDiscountPolicy"/>

</beans>

 

 

 

memberRepository가

ref="memberRepository"

를 통해서 생성자에서 넘어온다. memberRepository의 실제 구현체는 MemoryMemberRepository이다.

 

appConfig.xml은 Appconfig.java와 완전히 동일한 기능

@Configuration
public class AppConfig {

    @Bean
    public MemberService memberService() {
        return new MemberServiceImpl(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }

    @Bean
    public OrderServiceImpl orderService() {
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

    @Bean
    public DiscountPolicy discountPolicy() {
//        return new FixDiscountPolicy();
        return new RateDiscountPolicy();
    }
}

 

 

 

이제 테스트코드 XmlAppContext의

ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");

에서 appConfig.xml을 읽는다.

 

 

테스트코드 실행 결과

잘 동작한다!


그렇다면 스프링은 어떻게 이런 다양한 설정 형식을 지원하는가?

  •  'BeanDefinition'이라는 추상화
  • 역할과 구현을 개념적으로 나눈 것
  • xml또는 자바 코드를 읽어서 BeanDefinition을 만듦.
  • 스프링 컨테이너는 자바 코드인지, xml인지 몰라도 되고, 오직 BeanDefinition만 알면 됨!

BeanDefinition을 빈 설정 메타정보라 함.

  •  @Bean, <bean>당 각각 하나씩 메타 정보 생성.

스프링 컨테이너는 메타 정보를 기반으로 스프링 빈을 생성한다.

 

빈 설정 메타정보 확인

 

test/beanDefinition/BeanDefinitionTest

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@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);
        }
    }
}

 

실행 결과

뭐가 참 많다

Definitoin 정보가 상당히 많은데, 필요할 때 찾아보면 될 것 같다.

 

[출처] 스프링 핵심 원리 - 기본편, 김영한님