Spring Container와 @Bean

최준호·2021년 7월 6일
0

Spring

목록 보기
3/47

Spring 적용해보기

  • AppConfig Spring 기반으로 변경

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

기존의 AppConfig 파일을 Spring annotation을 사용하여 Spring Container로 등록합니다.

  • Spring Container란
    • ApplicationContext를 Spring Container라 부릅니다.
    • AppConfig에서 개발자가 직접 객체를 생성하고 DI를 했지만 이제는 Spring Container가 대신 해줍니다.
    • @Configuration이 붙은 AppConfig의 정보를 사용하고 @Bean이 붙은 메서드를 호출해서 사용할 수 있습니다. 또한 @Bean이 붙은 메서드들을 스프링 빈이라 부릅니다.
    • 스프링 빈으로 등록한 메서들은 아래와 같이 AnnotationConfigApplicationContext 메서드로 AppConfig.class 파일을 등록해주고 AppConfig에 설정해놓은 DI들을 이름으로/타입으로 조회할 수 있습니다.
public class ApplicationContextBasicFindTest {
    AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(AppConfig.class);

    @Test
    @DisplayName("빈 이름으로 조회")
    void findBeanByName(){
        MemberService memberService = ac.getBean("memberService", MemberService.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    @Test
    @DisplayName("타입으로 조회")
    void findBeanByType(){
        MemberService memberService = ac.getBean(MemberService.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    @Test
    @DisplayName("구체 타입으로 조회")
    void findBeanByName2(){
        MemberService memberService = ac.getBean("memberService",MemberServiceImpl.class);
        assertThat(memberService).isInstanceOf(MemberServiceImpl.class);
    }

    //test는 항상 실패 test까지
    @Test
    @DisplayName("빈 이름으로 조회X")
    void findBeanByNameX(){
        assertThrows(NoSuchBeanDefinitionException.class, () -> ac.getBean("XXXXX", MemberService.class));
    }

}
  • 스프링 빈 조회하기
    • ac는 위 예시코드의 변수명입니다.
    • ac.getBean(빈이름, 타입)
    • ac.getBean(타입)
    • 위 두 방법으로 조회가 가능하지만 타입은 추천하지 않는다.
    • NoSuchBeanDefinitionException == 조회할 수 없는 빈일 경우 예외 발생
  • 동일한 타입이 2개 이상 있는 스프링 빈 조회하기
    • ac.getBeansOfType()을 사용하면 해당 타입의 모든 빈이 조회 가능합니다.
    • ac.getBean(타입)으로 2개 이상이 존재하는 빈을 조회할시 NoUniqueBeanDefinitionException 예외처리가 발생합니다.
    • ac.getBean(빈이름, 타입)으로 조회하면 예외가 터질일이 없습니다.
  • 스프링 빈의 상속관계
    • 스프링 빈의 부모타입으로 조회하면 자식타입도 함께 조회됩니다.
    • java 객체의 최고 부모인 Object로 조회하면 모든 스프링 빈을 조회할 수 있습니다.

BeanFactory

  • BeanFactory란
    • 스프링 컨테이너의 최상위 인터페이스입니다.
    • 스프링 빈을 관리하고 조회하는 역할을 담당합니다.
    • getBean()을 제공하는 곳입니다.

ApplicationContext

  • ApplicationContext란
    • BeanFoctory를 기능을 상속받아 제공합니다.
    • BeanFoctory의 빈 조회, 관리 기능 뿐만 아니라 다른 부가기능을 지원합니다.
  • ApplicationContext 지원 기능
    1. MessageSource
      • 한국에서는 한국어, 영어권에서는 영어 사이트를 제공할 수 있도록 소스를 나눌수 있다.
    2. EnvironmentCapable
      • 환경변수를 로컬, 개발, 운영등으로 구분하여 나눌수 있도록 처리해준다.
    3. ApplicationEventPublisher
      • 이벤트를 발행하고 구독하는 모델을 편리하게 지원한다.
    4. ResourceLoader
      • 파일, 클래스패스, 외부 등에서 리소스를 편리하게 조회할 수 있도록 지원한다.
  • 스프링 빈의 메타 정보
    • 스프링 빈의 정보를 어디서 관리하는 것일까? Spring Container에서 등록을 하고 관리한다고 알고는 있지만 java로 spring을 설정하기도 하고 xml로 설정하기도 하며 json으로도 설정할 수 있습니다. 그렇다면 이 정보를 어떻게 spring에서 동일하게 처리해줄 수 있는걸까요?
    • BeanDefinition이라는 추상화가 있기 때문에 가능

  • 스프링 빈의 메타 정보 확인하기

    public class BeanDefinitionTest {
      AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext (AppConfig.class); 
    
      @Test 
      @DisplayName("빈 설정 메타정보 확인") 
      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); 
          } 
        } 
      }
    }

위 코드를 실행시

위와 같이 Bean의 메타 정보를 확인할 수 있습니다.

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

출처 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
코딩을 깔끔하게 하고 싶어하는 초보 개발자 (편하게 글을 쓰기위해 반말체를 사용하고 있습니다! 양해 부탁드려요!) 현재 KakaoVX 근무중입니다!

0개의 댓글