六、spring ioc之AnnotationConfigApplicationContext源碼解析

AnnotationConfigApplicationContext是Spring用來加載注解配置的ApplicationContext,它是如何加載所有的bean,與ClassPathXmlApplicationContext有什么區(qū)別,讓我們接下來揭開它的神秘面紗。

類圖

AnnotationConfigApplicationContext

這里我們拿AnnotationConfigApplicationContext與ClassPathXmlApplicationContext對比,由一、spring ioc之ClassPathXmlApplicationContext源碼解析我們知道,ClassPathXmlApplicationContext加載bean的邏輯是在AbstractRefreshableApplicationContext的refreshBeanFactory()方法中,但是我們從類圖中可以看出,AnnotationConfigApplicationContext并沒有實現(xiàn)這個類,那么它是如何加載bean的呢?

初始化

public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    register(annotatedClasses);
    refresh();
}
  1. this()
private final AnnotatedBeanDefinitionReader reader;
private final ClassPathBeanDefinitionScanner scanner;
public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

無參構(gòu)造函數(shù)中主要是初始化AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner兩個類。這里主要關注AnnotatedBeanDefinitionReader,跟蹤這個類的初始化發(fā)現(xiàn)它會注冊一堆BeanFactoryPostProcessor處理器,我們只需關注ConfigurationClassPostProcessor。

public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
            BeanDefinitionRegistry registry, Object source) {
   ...
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
            RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
            def.setSource(source);
            beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }
    ...
}
  1. register(annotatedClasses)
    這個方法主要是把所有的配置類注冊成bean。
  2. refresh()
    一個很熟悉的方法,因為ClassPathXmlApplicationContext加載也調(diào)用了它,但是ClassPathXmlApplicationContext在調(diào)用obtainFreshBeanFactory()的時候就把所有的bean加載完成,但是AnnotationConfigApplicationContext并沒有繼承自AbstractRefreshableApplicationContext,所以在obtainFreshBeanFactory()這步還是沒有加載bean。真正加載bean的操作是在invokeBeanFactoryPostProcessors(beanFactory),這個方法調(diào)用所有實現(xiàn)BeanFactoryPostProcessor接口的bean。那么BeanFactoryPostProcessor又是干嘛的呢?

BeanFactoryPostProcessor處理器

和BeanPostProcessor原理一致,Spring提供了對BeanFactory進行操作的處理器BeanFactoryProcessor,簡單來說就是獲取容器BeanFactory,這樣就可以在真正初始化bean之前對bean做一些處理操作。BeanFactoryProcessor定義如下:

public interface BeanFactoryPostProcessor {
    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子類,也只要一個方法

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

調(diào)用邏輯

AbstractApplicationContext#refresh()中調(diào)用了invokeBeanFactoryPostProcessors(beanFactory);這個方法邏輯如下:

  1. 遍歷所有實現(xiàn)了BeanDefinitionRegistryPostProcessor接口的bean
  2. 調(diào)用實現(xiàn)了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry
  3. 調(diào)用實現(xiàn)了Ordered接口的BeanDefinitionRegistryPostProcessors的postProcessBeanDefinitionRegistry
  4. 調(diào)用普通的BeanDefinitionRegistryPostProcessors(沒有實現(xiàn)Ordered接口和PriorityOrdered接口)的postProcessBeanDefinitionRegistry
  5. 遍歷所有實現(xiàn)BeanFactoryPostProcessor接口的bean,剩下的操作和BeanDefinitionRegistryPostProcessors的處理邏輯是一樣的。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容