IT 정보/Spring

[Spring] 스프링 컨테이너와 빈 ( 생성, 등록, 조회 )

개발하는 동그리 2022. 6. 17. 23:47

Spring Container 생성

사진 1. 스프링 컨테이너 생성

  • ApplicationContext는 인터페이스(다형성)이며, 스프링 컨테이너라고 부른다. 
  • AppConfig를 사용했던 방식을 애노테이션 기반의 자바 설정 클래스로 스프링 컨테이너를 만든 것이다.
  • new AnnotationConfigApplicationContext(AppConfig.class); 는 ApplicationContext인터페이스의 구현체이다.
  • 스프링 컨테이너는 (BeanFactory, ApplicationContext)로 구분할 수 있다. 일반적으로 ApplicationContext 사용한다.
  • 스프링 컨테이너 생성 시 구성 정보(AppConfig)를 입력해야 한다. 

 

Spring Bean 등록

사진 2. 스프링 빈 등록

 

  • @Bean 애노테이션을 사용해 각 메서드에 붙여주면 Bean이 등록된다. 
  • 빈 이름 = 메서드 명 / 빈 객체 = return 되는 객체명
    •  @Bean(name="choonsik"  이와 같이 이름을 변경할 수 있으나 원래 메서드명 사용을 가급적 추천하고, 빈 이름이 중복되지 않도록 주의한다. 중복될 경우 기존 빈 값을 덮어쓰거나 오류를 발생시킬 수 있다.
  • 자바 코드로 스프링 빈을 등록하면, 생성자를 호출하는 것과 동시에 의존관계 주입도 한번에 처리된다.

 

 

등록된 Bean 조회

사진 3. 모든 빈 출력

beanDefinitionName = org.springframework.context.annotation.internalConfigurationAnnotationProcessorobject = org.springframework.context.annotation.ConfigurationClassPostProcessor@2e61d218
beanDefinitionName = org.springframework.context.annotation.internalAutowiredAnnotationProcessorobject = org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor@3569fc08
beanDefinitionName = org.springframework.context.annotation.internalCommonAnnotationProcessorobject = org.springframework.context.annotation.CommonAnnotationBeanPostProcessor@20b12f8a
beanDefinitionName = org.springframework.context.event.internalEventListenerProcessorobject = org.springframework.context.event.EventListenerMethodProcessor@e84a8e1
beanDefinitionName = org.springframework.context.event.internalEventListenerFactoryobject = org.springframework.context.event.DefaultEventListenerFactory@2e554a3b

beanDefinitionName = appConfigobject = hello.core.AppConfig$$EnhancerBySpringCGLIB$$ccc7ff19@54a67a45
beanDefinitionName = memberServiceobject = hello.core.member.MemberServiceImpl@7d42c224
beanDefinitionName = memberRepositoryobject = hello.core.member.MemoryMemberRepository@56aaaecd
beanDefinitionName = orderServiceobject = hello.core.order.OrderServiceImpl@522a32b1
beanDefinitionName = discountPolicyobject = hello.core.discount.FixDiscountPolicy@35390ee3
  • 1~10줄은 스프링 내부에서 사용되는 빈
  • 11~15줄은 내가 등록한 빈 (Config도 Bean으로 등록됨)
  • 모든 빈을 출력할 때 ac.getBeanDefinitionName()을 사용하면 스프링에 등록된 모든 빈 이름을 조회
  • ac.getBean()을 사용하면 빈 이름으로 빈 객체(인스턴스)를 조회한다. 

 

사진 4. 등록한 빈 출력

Name = appConfigobject = hello.core.AppConfig$$EnhancerBySpringCGLIB$$ccc7ff19@2e61d218
Name = memberServiceobject = hello.core.member.MemberServiceImpl@3569fc08
Name = memberRepositoryobject = hello.core.member.MemoryMemberRepository@20b12f8a
Name = orderServiceobject = hello.core.order.OrderServiceImpl@e84a8e1
Name = discountPolicyobject = hello.core.discount.FixDiscountPolicy@2e554a3b
  • 내가 등록한 애플리케이션 빈 출력
  • 스프링에서 사용하는 빈 = getRole()
  • 사용자가 등록한 빈 = ROLE_APPLICATION
  • 스프링 내부에서 사용하는 빈 = ROLE_INFRASTRUCTURE

 

사진 5. 일반적인 빈 조회

  • (빈 이름 + 인터페이스 타입)으로 조회 가능 
  • (타입) 만으로 조회 가능 (같은 타입의 빈이 여러 개일 경우 에러 발생)
  • (빈 이름 + 구현체 타입)으로 조회 가능
  • 존재하지 않는 빈 이름으로 조회 (항상 예외도 테스트해볼 것) ⭐⭐⭐⭐

 

사진 6. 상속관계에서 빈 조회

 

  • 상속 관계에서 부모 타입을 조회하면 자식 빈들은 모두 조회된다. (자바의 최상위층 object타입 조회 -> 모든 빈 조회 )

 

BeanFactory

  • 스프링 컨테이너의 최상위층 인터페이스
  • 스프링 빈을 관리하고 조회하는 역할
  • getBean() 제공
  • 우리가 그동안 사용한 기능은 beanFactory가 제공하는 기능

 

ApplicationContext

사진 7. ApplicationContext가 상속받는 인터페이스 종류

  • BeanFactory 기능을 모두 상속받아서 제공
  • + 부가기능 가지고 있음
    • MessageSource interface : 언어를 상황에 맞게 국제화
    • EnvironmentCapable interface : 로컬, 개발, 운영을 구분해서 처리
    • ApplicationEventPublisher interface : 이벤트를 발행하고 구독하는 모델을 편리하게 지원 
    • ResourceLoader : 파일, 클래스 패스, 외부 등에서 리소스를 편리하게 조회

 

BeanDefinition

사진 8. BeanDefinition 메타정보 직접 확인

beanDefinition = Generic bean: class [hello.core.AppConfig$$EnhancerBySpringCGLIB$$ccc7ff19]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=nullbeanDefinition = Generic bean: class [hello.core.AppConfig$$EnhancerBySpringCGLIB$$ccc7ff19]; scope=singleton; abstract=false; lazyInit=null; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null

beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfigbeanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig

beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberRepository; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfigbeanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=memberRepository; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig

beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=orderService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfigbeanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=orderService; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig

beanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=discountPolicy; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfigbeanDefinition = Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=appConfig; factoryMethodName=discountPolicy; initMethodName=null; destroyMethodName=(inferred); defined in hello.core.AppConfig

BeanDefinition 이란?

 

  • BeanDefinition는 빈 설정 메타정보로 불림
  • BeanDefinition이 스프링 빈 메타정보를 생성하고 스프링 컨테이너는 BeanDefinition에만 의존
  • 스프링 컨테이너는 이 메타정보를 기반으로 스프링 빈을 생성

BeanDefinition 이 가지고 있는 정보

  • BeanClassName : 생성할 빈의 클래스 명
  • FactoryBeanName : 팩토리 역할의 빈을 사용할 경우 ex). AppConfig
  • factoryMethodName : 빈을 생성할 팩토리 메서드 지정 ex). memberService
  • Scope : (default) 싱글톤
  • lazyInit : 스프링 컨테이너를 생성할 때 빈을 생성하는 것이 아닌, 실제 빈을 사용할 때까지 최대한 생성을 지연처리하는지 여부 
  • InitMethodName : 빈을 생성하고, 의존관계를 적용한 뒤에 호출되는 초기화 메서드명
  • DestroyMethodName : 빈의 생명주기가 끝나서 제거하기 직전에 호출되는 메서드명
  • Constructor arguments, Properties : 의존관계 주입에서 사용  

'IT 정보 > Spring' 카테고리의 다른 글

[Spring] AOP 기본 개념  (47) 2022.06.21
[Spring] 컴포넌트 스캔  (44) 2022.06.20
[Spring] Bean Scope (Singleton pattern)  (43) 2022.06.16
[Spring] 스프링 컨테이너  (12) 2022.06.16
[Spring] FrameWork  (36) 2022.06.15