hoon's bLog

Spring gradle project 스프링 핵심 원리 기본편 | XML 설정 사용 및 BeanDefinition 스프링 빈 설정 메타 정보 본문

IT/Spring

Spring gradle project 스프링 핵심 원리 기본편 | XML 설정 사용 및 BeanDefinition 스프링 빈 설정 메타 정보

개발한기발자 2024. 4. 19. 08:23
반응형


본 포스팅은 인프런에 있는 인터넷 강좌인,

김영한 강사님의 스프링 핵심 원리 기본편을 공부하며,

개인적으로 공부하고, 정리하는 용도로 포스팅을 해보겠다.

 

Spring gradle project 환경설정 및 회원 가입 서비스 예제 만들기
Spring gradle project 주문/할인 도메인 설계

Spring gradle project 객체 지향 원리 적용

Spring gradle project AppConfig 리팩토링 OCP 위반 해결 및 중복 제거

Spring gradle project 좋은 객체 지향 설계 5가지 원칙 적용 및 스프링 전환

Spring gradle project 스프링 컨테이너와 스프링 빈

Spring gradle project BeanFactory, ApplicationContext 이해 및 차이

XML 설정 사용

  • 최근에는 스프링 부트를 많이 사용하면서 XML기반의 설정은 잘 사용하지 않는데, 아직 많은 레거시 프로젝트 들
    이 XML로 되어 있고, 또 XML을 사용하면 컴파일 없이 빈 설정 정보를 변경할 수 있는 장점도 있으므로 알고 있는 것도 괜찮다.
  • GenericXmlApplicationContext를 사용하면서 xml 설정 파일을 넘기면 된다.
  • xml 파일 경로 : src/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>

 

XmlAppConfig 사용 자바 코드

import hello.core.member.MemberService;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;

import static org.assertj.core.api.Assertions.assertThat;

public class XmlAppContext {

    @Test
    void xmlAppContext() {
        ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        assertThat(memberService).isInstanceOf(MemberService.class);
    }
}
  • XML 설정 파일(appConfig.xml)을 기반으로 애플리케이션 컨텍스트를 생성해서, 이 컨텍스트는 Spring 빈의 설정과 생성을 관리다.
  • getBean("memberService", MemberService.class) 메서드를 통해, XML 파일에서 정의된 memberService 빈을 로드합니다. (로드할 빈의 타입을 명시)

스프링 빈 설정 메타 정보 - BeanDefinition

  • BeanDefinition을 빈 설정 메타정보라 한다.
    @Bean, <bean> 당 각각 하나씩 메타 정보가 생성된다. 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성한다.
  • Spring은 BeanDefinition이라는 추상화를 통해 역할과 구현을 개념적으로 나누었다.
    XML을 읽어서, 자바 코드를 읽어서 BeanDefinition을 만들면 된다.
    스프링 컨테이너는 자바 코드인지, XML인지 몰라도 되고, 오직 BeanDefinition만 알면 된다.

AnnotationConfigApplicationContext는 AnnotatedBeanDefinitionReader를 사용해서 AppConfig.class를 읽고 BeanDefinition을 생성한다.
GenericXmlApplicationContext는 XmlBeanDefinitionReader를 사용해서 appConfig.xml 설정 정보를 읽고 BeanDefinition 을 생성한다.
새로운 형식의 설정 정보가 추가되면, XxxBeanDefinitionReader를 만들어서 BeanDefinition을 생성하면 된다.

 

BeanDefinition 정보

  • BeanClassName : 생성할 빈의 클래스 명(자바 설정 처럼 팩토리 역할의 빈을 사용하면 없음)
  • factoryBeanName : 팩토리 역할의 빈을 사용할 경우 이름, 예) appConfig
  • factoryMethodName : 빈을 생성할 팩토리 메서드 지정, 예) memberService
  • Scope : 싱글톤(기본값)
  • lazyInit : 스프링 컨테이너를 생성할 때 빈을 생성하는 것이 아니라, 실제 빈을 사용할 때까지 최대한 생성을 지연 처리 하는지 여부
  • InitMethodName : 빈을 생성하고, 의존관계를 적용한 뒤에 호출되는 초기화 메서드 명
  • DestroyMethodName : 빈의 생명주기가 끝나서 제거하기 직전에 호출되는 메서드 명
  • Constructor arguments, Properties : 의존관계 주입에서 사용한다. (자바 설정 처럼 팩토리 역할의 빈을 사용하면 없음)
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.support.GenericXmlApplicationContext;

public class BeanDefinitionTest {

    // AppConfig.java or appConfig.xml 모두 사용 가능
    // 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);
            }
        }
    }
}
  • BeanDefinition을 직접 생성해서 스프링 컨테이너에 등록할 수 도 있다.
    (실무에서 BeanDefinition을 직접 정의하거나 사용할 일은 거의 없다.)

코딩 뿐만 아니라 어떤 분야든,

깊이 파고 들어가면 한도 끝도 없다.

어떻게 보면 불필요하고, 비효율적으로 느껴지기도 한다.

하지만 이렇게 잠깐이나마 알았었던 부분들이 나중에 깨우쳐지기도 하고,

그러면서 흩어졌던 개념의 퍼즐들이 맞춰지는 부분들이 있기 때문에,

배움에 있어 불필요한 것은 없다고 생각한다.

 

그저 계속 배우면서 나아가자.

 

끝.

 

728x90
반응형