[기본기] 6-4. 다양한 설정방법들, BeanDefinition

khyojun·2022년 9월 29일
0
post-thumbnail

본 게시글은 김영한님의 스프링 핵심 원리 기본편을 정리한 글입니다.


📌 다양한 설정 방법들 JAVA & XML

스프링 컨테이너에서는 여러가지 형식의 설정 정보를 받을 수 있도록 하였다고 한다.
ex) 자바 코드, xml 등등

위 그림 처럼 각각보면 자바코드, xml, 그리고 뭐 xxx형식을 만들겠다고 한다면 그 형식을 만들어서도 사용을 할 수도 있다고 한다.

이때까지 우리가 예제 코드를 작성하면서 봤었던 AnnotationConfigApplicationContext는 자바코드로 직접 사용한 것이고 그 옆에 있는 GenericXmlApplicationContext는 xml 설정 정보를 활용하여서 설정해나가는 방법인데 실제로는 xml을 활용해서 현재는 많이 하고 있지는 않지만 이전의 레거시 프로젝트들을 보게 되면 이런 부분들이 들어있는 부분들이 있음으로 한 번쯤은 이런 부분 확인하는것이 좋을 거 같다.

자바 코드 설정 방법

우리는 이미 답을 알고 있다.

    ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

이런식으로 설정 정보에 해당하는 클래스를 컨테이너에 넣어주게 되는 것이다.

xml 설정 방법

📂 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="practicecore.ptcore.member.MemberServiceImpl">
        <constructor-arg name="memberRepository" ref="memberRepository" />
    </bean>

    <bean id="memberRepository" class="practicecore.ptcore.member.MemoryMemberRepository"/>

    <bean id="orderService" class="practicecore.ptcore.order.OrderServiceImpl">
        <constructor-arg name="memberRepository" ref="memberRepository"/>
        <constructor-arg name="discountPolicy" ref="discountPolicy"/>
    </bean>

    <bean id="discountPolicy" class="practicecore.ptcore.discount.RateDiscountPolicy"/>

</beans>
   ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");

위와 같은 xml파일을 컨테이너로 부를때 GenericXmlApplicationContext를 활용하여 불러서 설정 정보를 호출하였다. 위의 xml파일은 라는 태그와 이라는 태그 그리고 이라는 태그들이 눈에 띄는데 이걸 이 하나만 바라보지 말고 다음 코드와 함께 비교해보면 금방 눈에 들어올 것 같다.

📂 AppConfig.java

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

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

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

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

결론부터 얘기하자면 위 설정 정보와 xml의 태그들을 비교해보면 결론은 똑같은 설정 정보이다. 그냥 형태만 다른 것 뿐이었다는 것을 알 수 있었다.

📌 그러면 xml인지 자바인지 어떻게 암? BeanDefinition!

우리가 위 제목과 같이 BeanDefinition이라는 친구가 있었기에 우리가 xml로 설정을 하든 자바를 하든 따로 어떤 형식을 만들어서 하든 상관이 없다.

그러면 본격적으로 BeanDefinition이 무엇일까?

BeanDefinition은 어떻게 보면 추상화를 한 것이다. 그니까 어떻게 보면 이런 것인데 강의에서는 역할과 구현을 나눈 것이라고 말씀을 해주셨다. 그러면 xml을 사용을 하게 된다면 BeanDefinition에서 xml로 받아들이게 되고 그리고 자바 코드를 사용을 하면 자바 코드로 받아들이게 된다는 것이다.
그러면 이러면 실제로 스프링은 이게 무슨 코드인지 직접적으로 알 필요가 없다. 그니까 BeanDefinition이 결국 어떤 것인지 알아서 반환을 해준다는 것이다.

그러면 BeanDefinition을 빈 설정 메타정보라고 부른다. 그니까 위에 작성하였던 @bean, <bean> 를 통하여서 메타 정보를 하나씩 얻는다고 한다. 그렇게 스프링 컨테이너는 빈 메타정보들을 받아오게 된다. 그러면? 스프링 빈을 생성하게 된다. 그림을 보게 되면

아까 위에 되게 글을 장황하게 작성을 하였었는데 결론을 보게 되면 BeanDefinition을 통하여서 스프링 컨테이너에 알아서 잘 딱 깔끔하게 센스있게 넣어주는 친구였던 거 같다.

BeanDefinition에 대한 여러가지 정보들이다.

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

public class BeanDefinitionTest {

  AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

  @Test
  @DisplayName("빈 설정 메타정보 확인")
  void findBeanDefitnition(){
      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을 실제로는 막상 직접 정의하거나 사용하지는 않고 그리고 오늘 한 xml로 설정하는 부분도 실제로는 많이 작성을 하지는 않지만 생각을 해보게 되니 뭐 이걸 왜 배우냐? 라는 생각이 들 수 있는 부분이기도 한데 언젠가 레거시 프로젝트들을 보면 언젠가 한 번 보게 될 것이라고 생각이 들긴 하였다.

그래서 오늘의 한줄평...

BeanDefinition을 통하면 알아서 다 해결

출처

  1. 김영한님의 스프링 핵심 원리 기본편(https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8)
profile
코드를 씹고 뜯고 맛보고 즐기는 것을 지향하는 개발자가 되고 싶습니다

0개의 댓글