스프링 컨테이너는 다양한 형식의 설정 정보를 받아드릴 수 있게 설계되어 있다.
Table of Content
자바 코드 설정 사용 방식
현재까지 사용했던 new AnnotationConfigApplicationContext(AppConfig.class); 처럼 해당 클래스를 통해 자바 코드로 된 설정 정보를 넘기는 방법
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
Java
복사
public class MemberApp {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
...
}
Java
복사
XML 설정 사용 방식
위 AppConfig.java를 대신하여 appConfig.xml 소스코드를 설정 정보로 인식하게 하는 방법이다. 문법은 상이하나 거의 비슷한 구조를 가지고 있다. <bean> 과 같은 태그로 변경되고 속성으로 관리하는 문법이 사용된다.
<?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>
XML
복사
XML 설정 파일을 로드하여 사용하기 위해서는 ApplicationContext의 구현체를 GenericXmlApplicationContext를 사용해야 한다. 또한 xml의 경로는 main/resources/appConfig.xml 처럼 위치하는 것을 기본 컨텍스트 경로로 한다.
package hello.core.xml;
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 XmlAppContextTest {
@Test
void xmlAppContext() {
ApplicationContext ac = new GenericXmlApplicationContext("appConfig.xml");
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
Java
복사
XML 방식은 최근 권장되지 않는것 처럼 보이는데 레거시 프로젝트에서 자주 보일 수 있으며 현재도 사용 될 수 있기 때문에 대치하는 방법을 알아둬야 할 것 같다.
스프링 빈 설정 메타 정보 - BeanDefinition
위 처럼 스프링 컨테이너는 설정 형식을 어떻게 지원 하는 것인가?
스프링 컨테이너가 BeanDefinition이라는 추상화 인터페이스를 의존하고 있기 때문이다. (OCP 확장오픈 수정폐쇄가 적용되어 있기 때문) 따라서 BeanDefinition 추상화의 실 구현 객체 변경에 따라 유연하게 설정 파일을 선택하게 되는 것이다.
각 스프링 컨테이너 구현체(ex:AnnotationConfigApplicationContext)는 각자의 리더(Reader)를 통해 정보를 읽어 BeanDefinition을 생성하게 된다.
이는 할인 정책만 의존하고 있는 주문 서비스가 할인 정책만 알고 있어도 되는 상황과 유사하다. 스프링 컨테이너는 BeanDefinition인 빈 메타 정보만 알고 있어도 되는 것 같다.
예로 AppConfig.class를 통해 자바 코드를 설정 정보로 사용한 경우 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;
public class BeanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 설정 메타정보 확인")
void findApplicationBeanMetaInfo() {
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);
}
}
}
}
Java
복사
조회를 통해 BeanDefinition 메타 정보인 빈 클래스 이름, 팩토리 빈 이름, 전역범위인 스코프, Lazy 처리 여부 등 정보를 확인 할 수 있다.
Related Posts
Search