前言
本文主要給大家介紹了關於Spring啟動時Context加載的相關內容,分享出來供大家參考學習,下面話不多說了,來一起看看詳細的介紹吧。
測試源碼下載test-annotation.zip
有如下的代碼
@Componentpublic class HelloWorldService { @Value("${name:World}") private String name; public String getHelloMessage() { return "Hello " + this.name; }}@Configurationpublic class BootStrap { @Bean public static HelloWorldService helloService() { return new HelloWorldService(); } public static void main(String[] args) { InstantiationStrategy instantiationStrategy = new SimpleInstantiationStrategy(); DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); beanFactory.setInstantiationStrategy(instantiationStrategy); AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(beanFactory); applicationContext.register(BootStrap.class); applicationContext.refresh(); HelloWorldService service = applicationContext.getBean(HelloWorldService.class); System.out.println(service.getHelloMessage()); applicationContext.close(); }} HelloWorldService.getHelloMessage方法簡單的返回name的值, BootStrap.main方法中使用AnnotationConfigApplicationContext 構造一個上下文對象, 為了演示的方便, 顯示的聲明了DefaultListableBeanFactory和InstantiationStrategy實例。通過applicationContext.getBean()獲取bean的引用,並調用service.getHelloMessage()方法。
上下文的加載主要發生在applicationContext.register方法和applicationContext.refresh方法中,
applicationContext.register方法的作用是為參數(使用@Configuration註解的class)生成BeanDefinition 對象並調用DefaultListableBeanFactory.registerBeanDefinition將BeanDefinition註冊到DefaultListableBeanFactory中。
applicationContext.refresh()的功能要更多,主要功能一的是調用PostProcessor為@Configuration類中的@Bean標註的方法生成對應的BeanDefinition對象,並註冊到DefaultListableBeanFactory中,功能二是遍歷DefaultListableBeanFactory中BeanDefinition, 產生真正的對象。
為@Configuration類中@Bean標註的方法生成BeanDefinition對象詳細過程如下
步驟1、找到合適的BeanDefinitionRegistryPostProcessor處理器
org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors() { ... //獲取適用的BeanDefinitionRegistryPostProcessor bean名稱String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); ... //根據beanName獲取PostProcessor, 處理@Configuration標註類的beanName為//org.springframework.context.annotation.internalConfigurationAnnotationProcessor //實現為org.springframework.context.annotation.ConfigurationClassPostProcessor ConfigurationClassPostProcessor postProcessor =beanFactory.getBean(postProcessorNames[0], BeanDefinitionRegistryPostProcessor.class)}步驟2、為@Configuration產生ConfigurationClass對象
//使用ConfigurationClassParser解析@Configuration標註的類,
//每一個@Configuration標註的類產生一個ConfigurationClass對象,
// ConfigurationClass.getBeanMethods()能獲得該類中所有使用@Bean標註的方法,
//@Bean標註的方法使用BeanMethod對象表示
org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(BeanDefinitionRegistry registry) { ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); parser.parse(configCandidates); parser.validate(); this.reader.loadBeanDefinitions(parser.getConfigurationClasses());}步驟3、@Bean標註的方法產生BeanDefinition並註入到DefaultListableBeanFactory中
org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(BeanMethod beanMethod) { ConfigurationClassBeanDefinition beanDef = new ConfigurationClassBeanDefinition(configClass); beanDef.setBeanClassName(configClass.getMetadata().getClassName()); beanDef.setFactoryMethodName(metadata.getMethodName()); //registry 是DefaultListableBeanFactory的實例this.registry.registerBeanDefinition(beanName, beanDefToRegister);}此過程的調用棧:
根據BeanDefinition生成實例過程的調用棧:
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對武林網的支持。