λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
Spring/Spring Internal

Spring Bean 이 λ“±λ‘λ˜λŠ” κ³Όμ •

by 주발2 2023. 12. 2.
λ°˜μ‘ν˜•

μŠ€ν”„λ§μ„ μ‚¬μš©ν•˜λ‹€ 보면 @Configuration, @Component, @Bean λ“±μ˜ μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 μŠ€ν”„λ§ μ»¨ν…Œμ΄λ„ˆμ— λΉˆμ„ λ“±λ‘ν•˜λŠ”λ°μš”, μ–΄λ– ν•œ 과정을 톡해 Bean 이 λ“±λ‘λ˜λŠ”μ§€ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

 

ν…ŒμŠ€νŠΈλŠ” μœ„μ™€ 같이 @Configuration μ–΄λ…Έν…Œμ΄μ…˜μ„ μ„€μ •ν•œ TestConfiguration ν΄λž˜μŠ€κ°€ μ‘΄μž¬ν•˜κ³ ,

main λ©”μ„œλ“œλ₯Ό ν¬ν•¨ν•œ Main ν΄λž˜μŠ€μ—μ„œ μ–΄λ…Έν…Œμ΄μ…˜ 기반의 AnnotationConfigApplicationContext 객체λ₯Ό μƒμ„±ν•˜κ³ , 이 μƒμ„±μžμ—λŠ” TestConfiguration 객체λ₯Ό μ£Όμž…ν•©λ‹ˆλ‹€.

 

μœ„ 과정을 톡해 μ–΄λ…Έν…Œμ΄μ…˜ 기반의 Spring Bean 이 λ“±λ‘λ˜λŠ” 과정을 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

 

 

BeanFactory

BeanFactory μΈν„°νŽ˜μ΄μŠ€λŠ” μŠ€ν”„λ§ ν”„λ ˆμž„μ›Œν¬μ—μ„œ μŠ€ν”„λ§ λΉˆμ„ μƒμ„±ν•˜κ³  κ΄€λ¦¬ν•˜λŠ” 데 μ‚¬μš©λ˜λŠ” 핡심 μΈν„°νŽ˜μ΄μŠ€λ‘œ μœ„ μ΄λ―Έμ§€μ˜ λ©”μ„œλ“œλ“€μ΄ μ‘΄μž¬ν•©λ‹ˆλ‹€.

 

직접 μœ„ μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ‚¬μš©ν•  일은 μ•„λ§ˆλ„(?) 없을 것 κ°™μŠ΅λ‹ˆλ‹€.

Git History

첫 컀밋이 2008년이고, λ§ˆμ§€λ§‰ 컀밋은 2023년인데 κ·Έ 사이에 λ³€κ²½λœ λ‚΄μš©μ΄ λ§Žμ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€.

 

 

ApplicationContext

 

ApplicationContext μΈν„°νŽ˜μ΄μŠ€λŠ” μœ„ μ΄λ―Έμ§€μ²˜λŸΌ BeanFactoryλ₯Ό ν¬ν•¨ν•œ λ‹€μ–‘ν•œ μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속받고 μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ λΉˆμ„ κ΄€λ¦¬ν•˜λŠ” BeanFactory μΈν„°νŽ˜μ΄μŠ€μ˜ κΈ°λŠ₯ 외에도 λΆ€κ°€ κΈ°λŠ₯λ“€(메세지 μ†ŒμŠ€, λ¦¬μ†ŒμŠ€ 관리, 이벀트 λ“±)의 μΈν„°νŽ˜μ΄μŠ€λ₯Ό 상속받아 κΈ°λŠ₯을 μ œκ³΅ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

 

 

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver {

...

 

μœ„ λ‹€μ΄μ–΄κ·Έλž¨μ²˜λŸΌ ApplicationContextλŠ” λ‹€μ–‘ν•œ κΈ°λŠ₯을 가진 μΈν„°νŽ˜μ΄μŠ€λ₯Ό μƒμ†ν•¨μœΌλ‘œμ¨ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ„ μœ„ν•œ 섀정듀을 μ œκ³΅ν•˜λŠ” μΈν„°νŽ˜μ΄μŠ€λΌκ³  보면 될 것 κ°™μŠ΅λ‹ˆλ‹€.

 

Git History

ν•΄λ‹Ή μΈν„°νŽ˜μ΄μŠ€ λ˜ν•œ 2008λ…„ 첫 컀밋 이후 μ•½ 15λ…„κ°„ 크게 λ³€κ²½λœ λ‚΄μš©μ΄ μ—†λ„€μš”. πŸ‘

 

 

Test

Main ν΄λž˜μŠ€μ—μ„œ ApplicationContext λ₯Ό AnnotationConfigApplicationContext νƒ€μž…μœΌλ‘œ μƒμ„±ν–ˆκΈ° λ•Œλ¬Έμ— 

ν•΄λ‹Ή 클래슀의 register λ©”μ„œλ“œ (μ•„λž˜ 이미지 165라인)에 브레이크 포인트λ₯Ό κ±Έκ³  디버깅을 ν•΄λ΄…μ‹œλ‹€.

μœ„ 처럼 register λ©”μ„œλ“œμ— 브레이크 포인트λ₯Ό 걸어놓고, ν•˜λ‚˜μ”© λ”°λΌμ„œ λ“€μ–΄κ°€λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

 

AnnotationConfigApplicationContext

AnnotationConfigApplicationContext Git History
AnnotationConfigApplicationContext

@Configuration μ–΄λ…Έν…Œμ΄μ…˜μ„ μ„€μ •ν•œ TestConfiguration 객체에 λŒ€ν•΄ Bean 을 λ“±λ‘ν•˜κΈ° μœ„ν•΄ μœ„ 라인이 μ‹€ν–‰λ˜κ³  있고,

reader와 beanFactory의 κ΅¬ν˜„μ²΄λŠ” μœ„ 이미지와 κ°™μŠ΅λ‹ˆλ‹€.

 

μ‹€μ œ reader의 register() λ©”μ„œλ“œλ₯Ό μ‹€ν–‰ν•˜κΈ° λ•Œλ¬Έμ—, reader(AnnotatedBeanDefinitionReader) 클래슀λ₯Ό λ”°λΌκ°€λ³΄κ² μŠ΅λ‹ˆλ‹€.

 

참고둜 AnnotationConfigApplicationContext ν΄λž˜μŠ€λŠ” μ–΄λ…Έν…Œμ΄μ…˜ 기반의 μžλ°” μ½”λ“œλ“€μ„ μ„€μ •ν•˜λŠ”λ° μ‚¬μš©ν•˜λ©° ApplicationConetxt μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„μ²΄ μž…λ‹ˆλ‹€.

 

 

 

AnnotatedBeanDefinitionReader

μ•„λž˜λŠ” AnnotationConfigApplicationContext ν΄λž˜μŠ€μ—μ„œ ν˜ΈμΆœν•œ this.reader.register() λΆ€λΆ„μ˜ μ½”λ“œμž…λ‹ˆλ‹€.

(registerBean() -> doRegisterBean() λ©”μ„œλ“œ 호좜)

AnnotatedBeanDefinitionReader

AnnotatedBeanDefinitionReader ν΄λž˜μŠ€λŠ” 빈의 등둝을 μœ„ν•œ μ–΄νƒ­ν„° ν΄λž˜μŠ€μž…λ‹ˆλ‹€.

  • AnnotatedGenericBeanDefinition: BeanDefinition μΈν„°νŽ˜μ΄μŠ€μ˜ κ΅¬ν˜„μ²΄λ‘œ μ–΄λ…Έν…Œμ΄μ…˜μ˜ 메타 데이터(빈의 속성값, μƒμ„±μž 정보, μŠ€μ½”ν”„ λ“±)λ₯Ό 가지고 μžˆλŠ” 클래슀
  • ScopeMetedata: Bean Scope의 μ •λ³΄λ‘œ defaultλŠ” "singleton"

 

κ·Έ μ™Έ 빈의 μš°μ„ μˆœμœ„λ₯Ό μ •ν• λ•Œ μ‚¬μš©ν•˜λŠ” Primary, Lazy, Qualifier 등이 μ½”λ“œμƒμ— λ³΄μ΄λŠ”λ°μš”, λΉˆμ„ μ„€μ •ν•  λ•Œ μž‘μ„±ν•˜λŠ” @Primary, @Lazy, @Qualifier μ–΄λ…Έν…Œμ΄μ…˜μ΄ μœ„ μ½”λ“œμƒμ—μ„œ μ‚¬μš©μ΄ λ˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

 

 

beanName

beanName 을 μƒμ„±ν•˜λŠ” μ½”λ“œμΈλ°μš”, μœ„ λ©”μ„œλ“œλ₯Ό 톡해 빈의 넀이밍이 기본적으둜 μ–΄λ– ν•œ λ°©μ‹μœΌλ‘œ μƒμ„±λ˜λŠ”μ§€ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

 

 

BeanDefinitionHolder: 빈의 정보λ₯Ό 가지고 μžˆλŠ” BeanDefinition μΈν„°νŽ˜μ΄μŠ€μ˜ Holder 클래슀

 

μœ„μ˜ 과정듀을 μˆ˜ν–‰ν•œ ν›„ λ§ˆμ§€λ§‰ 라인인 BeanDefinitionReaderUtils 클래슀의 registerBeanDefinition() λ©”μ„œλ“œλ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

(μ΄λ•Œ this.registry λŠ” AnnotationConfigApplicationContext νƒ€μž…)

 

 

 

BeanDefinitionReaderUtils

BeanDefinitionReaderUtils

beanName 을 κ°€μ Έμ˜€κ³ , registry에 빈 정보λ₯Ό μ €μž₯ν•˜λŠ” λ“± νŠΉλ³„ν•œ λ‚΄μš©μ€ μ—†λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

registry의 registerBeanDefinition() λ©”μ„œλ“œλŠ” AnnotationConfigApplicationContext 클래슀의 μƒμœ„ 클래슀인 GenericApplicationContext 클래슀의 registerBeanDefinition() λ©”μ„œλ“œκ°€ 싀행이 λ©λ‹ˆλ‹€.

GenericApplicationContext

μœ„μ—μ„œ beanFactory λŠ” DefaultListableBeanFactory 이기 λ•Œλ¬Έμ— ν•΄λ‹Ή 클래슀λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€.

 

 

 

DefaultListbaleBeanFactory

일반적으둜 bean 에 μ ‘κ·Όν•˜κΈ° μ „, λͺ¨λ“  bean definitions 듀을 λ¨Όμ € λ“±λ‘ν•©λ‹ˆλ‹€.

 

DefaultListbaleBeanFactory

μ‹€μ œ registerBeanDefinition λ©”μ„œλ“œλŠ” μ•½ 90라인정도 λ˜μ§€λ§Œ, λŒ€λΆ€λΆ„ μƒλž΅ν–ˆμŠ΅λ‹ˆλ‹€.

 

DefaultListbaleBeanFactory

Map<String, BeanDefinition> beanDefinitionMap ν•„λ“œμ— Bean 정보λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€.

 

 

정리

λ„ˆλ¬΄λ‚˜ λΉ λ₯΄κ²Œ ν›„λ‹€λ‹₯ μ§€λ‚˜κ°„ 것 κ°™μŠ΅λ‹ˆλ‹€.

μ–΄λ…Έν…Œμ΄μ…˜ (@Configuration, @Componenet λ“±λ“±) 기반 Spring Bean 이 λ“±λ‘λ˜λŠ” 과정을 κ°„λž΅νžˆ μ •λ¦¬ν•˜λ©΄ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

 

  1. AnnotationConfigApplicationContext
    • reader(AnnotatedBeanDefinitionReader) 의 register() 호좜
  2. AnnotatedBeanDefinitionReader
    • abd(AnnotatedGenericBeanDefinition) λ³€μˆ˜μ— Bean 의 정보 μ €μž₯ 및 BeanDefinitionReaderUtils.registerBeanDefinition() λ©”μ„œλ“œ 호좜
  3. BeanDefinitionReaderUtils
    • registry(AnnotationConfigApplicationContext - GenericApplicationContext) λ₯Ό 톡해 BeanDefinition 등둝
  4. DefaultListbaleBeanFactory
    • μ΅œμ’…μ μœΌλ‘œ Bean 을 λ“±λ‘ν•˜λŠ” 클래슀
    • Map<string, BeanDefinition> beanDefinitionMap ν•„λ“œμ— Bean 정보λ₯Ό μ €μž₯

 

 

λ°˜μ‘ν˜•

'Spring > Spring Internal' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

Spring @ComponentScan λ™μž‘ κ³Όμ •  (2) 2023.12.09

λŒ“κΈ€