본문 바로가기

Spring

Spring- 스프링 빈 메타 정보 설정(BeanDefinition)

BeanDefinition

  스프링 빈을 등록시에는 자바 코드에 @Bean 어노테이션을 통해서 빈 등록도 가능하지만 그 외에 xml을 이용하는 방식등, 여러 가지 방식을 통해서 스프링 빈을 등록하는 것이 가능하다. 이는 스프링 컨테이너가 자바코드, xml 파일을 읽는 것이 아니라 BeanDefinition만 읽기 때문에 가능하다. 또한 자바 코드와 xml은 BeanDefinition으로 추상화된다. 여기서 BeanDefinition을 "빈 설정 메타정보"라고 한다.

빈 메타 정보 생성과정

 

 즉, "자바 코드, xml, etc -> BeanDefinition로 추상화 -> 스프링 컨테이너가 BeanDefinition 읽어들임"의 과정이 있다. 여기서 스프링 컨테이너는 다른 건 신경 쓸 필요없이 BeanDefinition만 보면 되기 때문에, 또한 자바코드, xml은 모두 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 beanDefinition = ac.getBeanDefinition(beanDefinitionName);

            if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
                System.out.println("beanDefinitionName = " + beanDefinitionName +
                        " beanDefinition = " + beanDefinition);
            }
        }
    }
}

 xml로 스프링 빈 등록

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 beanDefinition = ac.getBeanDefinition(beanDefinitionName);

            if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
                System.out.println("beanDefinitionName = " + beanDefinitionName +
                        " beanDefinition = " + beanDefinition);
            }
        }
    }
}

 위의 두 코드는 기본적으로 ac가 자바코드를 참조하느냐, xml 파일을 참조하느냐 차이를 제외하고는 내부 로직은 모두 동일하다. 그냥 단순히 스프링 빈은 자바 코드로도, xml로도 혹은 그 외의 방식으로도 등록할 수 있다는 것을 보여주기 위해서 써놓았다.

 

팩토리 빈과 직접 등록

 팩토리 빈과 팩토리 메소드

package hello.core;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.discount.RateDiscountPolicy;
import hello.core.member.MemberService;
import hello.core.member.MemberServiceImpl;
import hello.core.member.MemoryMemberRepository;
import hello.core.order.OrderService;
import hello.core.order.OrderServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration // 팩토리 빈
public class AppConfig {
    @Bean  //팩토리 메소드
    public MemoryMemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
    @Bean
    public DiscountPolicy discountPolicy(){
        return new RateDiscountPolicy();
    }
    @Bean
    public MemberService memberService(){
        return new MemberServiceImpl(memberRepository());
    }
    @Bean
    public OrderService orderService(){
        return new OrderServiceImpl(memberRepository(), discountPolicy());
    }

}

 AppConfig와 같이 특정 클래스를 스프링에 등록한 후 등록된 클래스 메소드를 등록하는 방식의 경우, 등록된 클래스를

팩토리 클래스라고 한다. 등록된 메소드는 팩토리 메소드라고 한다.

 

 직접등록

 팩토리를 사용하지 않고 등록하는 것을 말한다.

 

결론

 위에서 한 말을 계속 반복하는 것 같긴한데 결론은 이거다.

@Bean으로 자바코드를 등록하나, <bean>으로 xml을 등록하나 결론적으론 모두 BeanDefinition으로 추상화된다. 그리고 스프링 컨테이너는 BeanDefinition을 읽어서 스프링 빈으로 등록한다.

'Spring' 카테고리의 다른 글

Spring- @configuration과 싱글톤  (0) 2023.01.24
Spring- 싱글톤  (0) 2023.01.24
Spring- BeanFactory와 ApplicationContext  (0) 2023.01.19
Spring- 빈 관련 내용 정리  (0) 2023.01.17
Spring- 스프링 컨테이너로 등록하기(2)  (0) 2023.01.17