21.04.03-04 TIL - Spring 핵심원리 - 3편

김정훈·2021년 4월 4일
0

📌 Spring 핵심원리 - 3편

<출처 : 인프런 Spring 핵심원리 : 김영한 강사님>

https://www.inflearn.com/roadmaps/373

➡️ ⌘ 스프링 컨테이너(Spring Container), 빈(Bean) 조회

컨테이너의 생성과정

ApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

인터페이스인 ApplicationContext를 스프링 컨테이너라고 한다.
그리고 AnnotationConfigApplicationContext는 ApplicationContext의 구현체이다.
스프링 컨테이너는 xml, 애노테이션 기반의 자바 설정 클래스로 만들 수 있다.
2편에서 살펴본 방식은 @Configuration을 통한 애노테이션으로 스프링 컨테이너를 만든 것이다.

new AnnotationConfigApplicationContext(구성(설정)정보 지정)
⟹ new AnnotationConfigApplicationContext(AppConfig.class)

(AppConfig클래스에는 @Configuration어노테이션이 적용되어 있다. 그래서 설정 정보로 사용이 가능하다.)
⟹ 그리고 이제 AppConfig.class에 @Bean이 적용되어 있는 객체들을 스프링 빈으로 등록한다.

💥주의사항 : Bean이름은 보통 메서드 이름을 사용하는 것이 관례이지만, Bean(name="내맘이다") 이런 방식으로 이름을 부여할 수 있지만, 이왕이면 관례를 따르는 것이 좋다.
💣 그럼에도 불구하고 사용해야 하는 경우에는, 같은 이름을 부여하게 된다면, 기존의 Bean을 덮어버리거나 설정에 따라 오류가 발생할 수 있다.

의존관계 설정 👉흐름 : 스프링 컨테이너는 설정 정보를 참고해서 의존관계를 주입한다.
memberService는 저장소만 필요하기 때문에 memberRepository만을 의존하고,
orderService 같은 경우 저장소, 할인 정책 두 가지가 다 필요하기 때문에, memberRepository+discountPolicy 모두 의존한다.

이런 방식으로 등록한 빈을 조회하는 방법

AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);
@Test
@DisplayName("빈 조회방법")
void findBean(){
	String[] beanDefinitionNames = ac.getBeanDefinitionNames();
    	for(String beanDefinitionNames = beanDefinitionNames){
        		BeanDefinition beanDefinition = ac.getBeanDefinition(beanDefinitionNames);
                	if(beanDefinition.getRole() == BeanDefinition.ROLE_APPLICATION){
                    		Object bean = ac.getBean(beanDefinitionName);
                            	System.out.println("name은 ="+beanDefinitionName+" /object 부분은 ="+ bean);
                                }
                  }
    }

ac.getBeanDefinitionNames() : 스프링에 등록된 모든 빈 이름을 조회해준다.
ROLE_APPLICATION : 일반적으로 사용자가 정의한 빈(ex. discountPolicy, memberRepository)
ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈

➡️ 스프링 빈 조회(기본)

:: 실제 개발시에는 BeanNullPoint가 뜰 때 어떤 Bean이 들어있는지 확인할 때 사용한다.
자주 사용하는 편은 아니라고 한다.**
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class)

1. 빈 이름+타입으로 조회
void findBeanName(){
	MemberService memberService = ac.getBean("memberService", MemberService.class);
    	assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
        // memberService가 MemberServiceImpl의 인스턴스이면 테스트 성공
 }
2. 오직 타입으로만 조회
 void findBeanType(){
 	MemberService memberService = ac.getBean(MemberService.class);
    	assertThat(memberService).isInstanceOf(MeberServiceImpl.class);
 }
3. 조회가 안되는 경우(실패 테스트)
void findBeanX(){
	Assertions.assertThrows(NoSuchBeanDefinitionException.class, () 
    ⟶ ac.getBean("xx", MemberService.class));
}
//ac.getBean부분이 없으면 NoSuchBeanDefinitionException에러가 터질 것이고, 그 에러가 터지면 테스트는 성공!

➡️스프링 빈 조회 - 상속관계

  • 부모 타입으로 조회하면 자식 타입도 함께 조회한다.
  • 최고 부모인 Object타입으로 조회하면 모든 스프링 빈을 조회한다.
AnnotationConfigApplicationContext ac = new  AnnotationConfigApplicationContext(AppConfig.class)
// 부모 타입으로 조회시, 자식이 둘 이상 있으면, 빈 이름을 지정하면 된다
void findBeanByParentTypeBeanName(){
	DisCountPolicy rateDiscountPolicy = ac.getBean("rateDiscountPolicy", DiscountPolicy.class);
    	assertThat(rateDiscountPolicy).isInstanceOf(RateDiscountPolicy.class);
}
// 특정 하위 타입으로 조회 : RateDiscountPolicy
void findBeanType(){
	RateDiscountPolicy bean = ac.getBean(RateDiscountPolicy.class);
    	assertThat(bean).isInstanceOf(RateDiscountPolicy.class);
}
// 부모 타입으로 조회하기 : DiscountPolicy
void findParentType(){
	Map<String, DiscountPolicy> beansOfType = ac.getBeansOfType(DiscountPolicy.class);
    	assertThat(beansOfType.size()).isEqualTo(2);
        for(String key:beansOfType.keySet()){
        	System.out.println("key값은 = "+ key +" /value값은 ="+beansOfType.get(key));
       }
}

➽ 이번에는 가볍게 스프링 컨테이너의 생성과정과 그 안에 빈들을 조회하는 방법을 정리했다.
빈을 조회하는 경우는 BeanNullPoint상황에 사용한다고 하는데, 그런 경우가 흔하지는 않다고 하지만, 생성과정과 이런 조회하는 방법 또한 숙지해놓으면 좋을 것 같다.

profile
WebDeveloper

0개의 댓글

관련 채용 정보