상속받은 인터페이스를 구현하는 AnnotationConfigApplicationContext(구현 클래스,구현체)
BeanFactory (빈 팩토리)
- 스프링 컨테이너 최상위 인터페이스
- 스프링빈을 관리하고 조회하는 역할 담당
- 이전 시간에 썼던 getBean()과 같이 사용했던 대부분의 기능은 빈팩토리에서 제공하는 기능이였다.
ApplicationContext
- 빈팩토리를 상속하는 인터페이스이므로 빈팩토리의 기능을 모두 상속받아서 제공한다.
- 빈팩토리와 차이는 뭘까? -> 빈을 관리하고 조회하는 기능(빈팩토리)은 물론이고 수많은 부가기능이 필요하기 때문에
다른 인터페이스도 상속하고있다.
다양한 설정 형식 지원 (자바코드 , XML)
이전에 AppConfig.class로 설정정보를 줘서 스프링컨테이너를 생성했듯이
appConfig.xml이라는 XML로도 생성이 가능하다.
맨 오른쪽것처럼 임의의 설정해서 사용할 수 도 있다.
물론 자바코드를 많이 사용한다.
XML 해보기
XmlAppContext.java
테스트파일을 생성해서 테스트해본다.
public class XmlAppContext {
@Test
void xmlAppContext() {
ApplicationContext ac = new GenericXmlApplicationContext(
"appConfig.xml"); //xml파일을 이용하여 스프링 컨테이너 생성
MemberService memberService = ac.getBean("memberService", MemberService.class);
assertThat(memberService).isInstanceOf(MemberService.class);
}
}
중복 빈 테스트파일 코드짤때 ,임의의 Config클래스 생성해서 했던것처럼 appConfig.xml를 생성해준다.
하지만 XML파일은 resources밑에 파일로 생성해준다.
오른쪽마우스 -> new -> XML Configuration file -> spring config 로 생성
<?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">
</beans>
이 내용은 기본으로 들어가있다.
밑에 빈 추가해준다. ( 멤버서비스, 멤버리포지토리, 디스카운트폴리시 등등 AppConfig.java에서 해줬던것처럼)
<?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="com.example.demo.member.MemberServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
</bean>
<bean id="memberRepository" class="com.example.demo.member.MemoryMemberRepository">
</bean>
<bean id="orderService" class="com.example.demo.order.OrderServiceImpl">
<constructor-arg name="memberRepository" ref="memberRepository"/>
<constructor-arg name="discountPolicy" ref="discountPolicy"/>
</bean>
<bean id="discountPolicy" class="com.example.demo.discount.RateDiscountPolicy">
</bean>
</beans>
위의 코드를 보면
AppConfig.java와 비슷하다는것을 알 수 있다. (형식만 xml인 느낌)
@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();
}
}
xml 파일로도 스프링컨테이너에 빈이 잘 등록되는것을 확인할 수 있었다.
스프링 빈 설정 메타 정보(BeanDefinition)
XML을 읽어서 <bean>을 보고 그냥 메타정보를 만들기만 하면된다.
java 코드를 읽어서 @Bean을 보고 그냥 메타정보를 만들기만 하면된다.
그 BeanDefinition이 자바로 된건지 xml로 된건지 뭐로된건지는 신경안쓴다 ( 역할에 의존한다. 구현에 의존하지않고)
자바코드 사용해서 스프링컨테이너를 생성할때 사용했던 AnnotationConfigApplicationContext는
Reader를 사용해서 AppConfig.class를 읽고 BeanDefinition(빈 메타정보)을 생성한다.
BeanDefinition(빈 메타정보) 살펴보기
BeanDefinitionTest.java
public class BeanDefinitionTest {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 설정 메타정보 확인")
//BeanDefinition 확인
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);
}
}
}
}
getBeanDefinition() 가 ApplicationContext에 없는 이유.
위의 테스트 출력 결과
beanDefinitionName = appConfig beanDefinition = Generic bean: class [com.example.demo.AppConfig$$SpringCGLIB$$0]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodNames=null; destroyMethodNames=null
beanDefinitionName = memberService beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in com.example.demo.AppConfig
beanDefinitionName = MemberRepository beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=MemberRepository; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in com.example.demo.AppConfig
beanDefinitionName = orderService beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=orderService; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in com.example.demo.AppConfig
beanDefinitionName = DiscountPolicy beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=DiscountPolicy; initMethodNames=null; destroyMethodNames=[(inferred)]; defined in com.example.demo.AppConfig
빈 메타정보이름 : 빈 이름
빈 메타정보 : 안에 엄청 많은 정보들이 담겨있다.
댓글