深入理解 Spring 環境初始化

終于,有一天我也來看Spring的源碼了,看了一陣之后感覺心情那叫一個舒暢,對Spring底層的實現也有了進一步的了解, 最直觀的感受就是Spring的命名風格很贊,很長,真的長到使人見名知意, 閑言少敘,開始整理筆記了

程序的入口

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);

跟進這個AnnotationConfigApplicationContext()程序的啟動入口, 注解配置的應用上下文.主要做了下面的三件事

  • 調用本類無參構造方法
  • 調用register(annotatedClasses) 將我們傳遞進來的配置類注冊進BeanFactoryBeanDefinitionMap
  • 刷新容器
    public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
        this();
        register(annotatedClasses);
        refresh();
    }

創建BeanFactory

https://img2018.cnblogs.com/blog/1496926/201910/1496926-20191014223256299-675993675.png

首先調用本類的無參構造方法,,通過上圖,可以看到,AnnotationConfigAllicationContext的父類是GenericApplicationContext但是,在執行本類的無參構造方法時會先執行父類的無參構造方法.它父類的無參構造方法我貼在下面,就做了一件事,初始化了Spring的BeanFactory,沒錯就是Spring的Bean工廠,由于兩者的繼承關系,我們就任務,AnnotationConfigApplicationContext的Bean工廠被初始化了

    public GenericApplicationContext() {
        this.beanFactory = new DefaultListableBeanFactory();
    }

創建AnnotatedBeanDefinitionReader加載

接著回到這個構造方法的源碼我貼在下面, 這個構造方法主要做了兩件事

  • 為應用的上下文創建reader讀取器, 讀取被添加了注解的類信息
  • 實例化了一個Scanner, 這個Scanner可以用去做包掃描的工作,但是Spring根據我們的配置信息去進行包掃描的工作時,并沒有使用這個掃描器,而是自己new 了一個,當前的掃描器可以理解成是方便程序員使用而創建的
    public AnnotationConfigApplicationContext() {
        this.reader = new AnnotatedBeanDefinitionReader(this); 
        this.scanner = new ClassPathBeanDefinitionScanner(this);
    }

下面跟進AnnotatedBeanDefinitionReader掃描器的創建過程,經過幾個沒有重要邏輯的方法,我們會進入registerAnnotationConfigProcessors(BeanDefinitionRegistry registry, @Nullable Object source),下面是源碼: 這算是Spring初始化的一個小高潮了!!!,為啥這樣說呢? 因下面的邏輯中,為Spring初始化過程中,構建BeanFactory提供了幾個開天辟地性質的RootBeanDefinition``

  • 首先是在為BeanFactory添加了兩個大組件
    • AnnotationAwareOrderComparator用于解析@Order@Priorty注解
    • ContextAnnotationAutowireCandidateResolver 提供了懶加載的支持
  • 然后就是往BeanFactory中的BeanDefinitionMap中添加了6個RootBeanDefinition
    • ConfigurationClassPostProcessor
    • AutowiredAnnotationBeanPostProcessor
    • ...
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
        BeanDefinitionRegistry registry, @Nullable Object source) {

    //   得到bean工廠
    DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
    if (beanFactory != null) {
        if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator)) {
            //  給Bean工廠添加原材料
            //  AnnotationAwareOrderComparator 主要能解析@Order注解和@Priority
            beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
        }
        if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver)) {
            //  ContextAnnotationAutowireCandidateResolver 提供處理懶加載(Lazy)相關的功能
            beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
        }
    }
    //   作用是方便傳遞參數BeanDefinitionHolder
    Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
    // BeanDefinition的注冊,這里很重要,需要理解注冊每個bean的類型
    //   就是判斷工廠中有沒有包含 CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME 名稱的bean, Spring在啟動時,工廠肯定是空的返回false , 加上! 表示ture
    if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {//configuration_annotation_processor_bean_name
        //   注意: 下面的ConfigurationClassPostProcessor實現了BeanDefinitionRegistryPostProcessor,間接實現了 BeanFactoryPostProcessor bean工廠的后置處理器
        //   RootBeanDefinition可以理解成 描述Spring內部類的Definition

        //   除了通過AnnotationedBeanDefinitionReader把 加上了注解的類加載成bean,下面的第二種方式, 通過new RootBeanDefinition, 進而將 XXX.class起來注冊進bean工廠
        //   這是使用第二種方式, 通過new Spring自己實現的BeanDefinition接口的類,將java轉換成 Bean 然后put進BeanFactory的BeanDefinitionMap中
        //   下面的111-666 就是最先放置進去的6個Spring的RootBean對象
        //   ---111---------------------------
        RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
        def.setSource(source);
        //   跟進去 registerPostProcessor
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        //AutowiredAnnotationBeanPostProcessor 實現了 MergedBeanDefinitionPostProcessor
        //MergedBeanDefinitionPostProcessor 最終實現了 BeanPostProcessor
        //   ---222---------------------------
        RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        //   ---333---------------------------
        RootBeanDefinition def = new RootBeanDefinition(RequiredAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, REQUIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
    if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {

        //   ---444---------------------------
        RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    // Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
    if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
        RootBeanDefinition def = new RootBeanDefinition();
        try {
            def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
                    AnnotationConfigUtils.class.getClassLoader()));
        }
        catch (ClassNotFoundException ex) {
            throw new IllegalStateException(
                    "Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
        }
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME)) {
        //   ---555---------------------------

        RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
    }

    if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME)) {
        //   ---666---------------------------
        RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
        def.setSource(source);
        beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
    }

    return beanDefs;
}

上面的代碼中有來如下兩個亮點:

亮點1:RootBeanDefinition

首先涉及到的知識點就是,Spring有哪幾種方式將對象轉成BeanDefinition? 其實是有兩種,第一種就是讓Spring通過Scanner去掃描包解析程序員提供的添加了注解的類,這是個自動完成的過程,第二種就是Spring通過new RootBeanDefinition等諸多的BeanDefinition接口的實現類, 然后將Spring原生的對象當成參數傳遞進去進而轉換成BeanDefinition, 當然,Spring在這里選擇的就是第二種方法

亮點2:ConfigurationClassPostProcessor

這個類很牛,為什么這么說呢? 先看一下他的繼承類圖

https://img2018.cnblogs.com/blog/1496926/201910/1496926-20191014223255758-1792965804.png

沒錯,他是6個RootBeanDefinition中唯一的一個實現BeanFactoryPostProcessor的,其他的五個RootBeanDifinition實現的都是BeanPostProcessor, 其實也不用懵逼,只要我們整明白這里說的BeanPostProcessorBeanFactoryPostProcessor的作用就好了,然后在這里我用下面的兩個模塊解釋

BeanPostProcessor

接口的抽象方法源碼如下:

public interface BeanPostProcessor {

@Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
@Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }
}

兩個方法名,見名知意: 第一個會在 對象的 constructor 之后,init()方法之前調用

第二個會在init()方法之后調用

但是,大家可以發現,它的調用時機都是在構造方法執行之后進行攔截,這時候BeanDefinition已經被實例化了

BeanFactoryPostProcessor

@FunctionalInterface
public interface BeanFactoryPostProcessor {

    void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;

}

它就比較厲害了, 這也是Spring牛的地方,它不僅僅會替我們維護這些Bean,而且還通過當前的BeanFactoryPostProcessor,為程序員開放一個缺口,讓程序員可以參與到Bean的創建過程中來,為什么這樣說呢, 其實大家可以看到,它唯一的抽象方法中的入參位置上是誰? 沒錯,就是BeanFactory, Bean工廠都給我們了,那不是想干啥干啥?

其次,它的作用時機是執行Bean的構造方法之前

最直接的應用場景: 當一個單例的Bean依賴 多例的Bean時,我們多次通過 應用的上下文獲取出來的單例bean的hashcode都是唯一的這沒錯,但是緊接著打印它依賴的多例對象的hashcode同樣是相同的,這種單例失效的問題,就可以根據這個知識點從容解決

前面說的ConfigurationClassPostProcessor就是BeanFactoryPostProcessor的實現類,并且它也不辱使命, 完美的使用作用時機不同的特點,在程序員提供的配置類的構造方法調用之前,就先入為主,圍棋生成了 cglib代理對象


接著看代碼,回到上面的代碼,我們看如何將RootBeanDefinition注冊進BeanFactory, 我從上面截取一行代碼放在這里

    //   跟進去 registerPostProcessor
        beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));

跟進這個registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)

private static BeanDefinitionHolder registerPostProcessor(
        BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

    definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
    //   registerBeanDefinition()
    registry.registerBeanDefinition(beanName, definition);
    return new BeanDefinitionHolder(definition, beanName);
}

我們關注這個registry.registerBeanDefinition(beanName, definition); , 可以看到,其實這個registerBeanDefinition()BeanDefinitionRegistry的抽象方法,我們要找的是它的實現類,那問題來了, 是誰實現他呢? 可以回到博客頂部,看看第一個圖,沒錯Spring的BeanFactory,也就是DefualtListableBeanFactory實現了這個接口,雖然有點意外,一個工廠竟然還是一個注冊器,但是這也是事實情況, 看看這個工廠是如何做的吧 .原函數很長,我截取了部分源碼如下: 它的解釋我寫在源碼的下面

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException {
            ...
            else {
                //   添加進入容器中, 最終的結果就是,這個map中存在哪些類,Spring的IOC中就有哪些類
                // Still in startup registration phase
                this.beanDefinitionMap.put(beanName, beanDefinition);
                //   單獨使用一個list存放名字
                this.beanDefinitionNames.add(beanName);

                this.manualSingletonNames.remove(beanName);
            }
            this.frozenBeanDefinitionNames = null;
        }

        if (existingDefinition != null || containsSingleton(beanName)) {
            resetBeanDefinition(beanName);
        }

可以看到,他將一開始的6個RootBeanDefinition全都都put進了一個map中, 下面這個map

private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);

key就是beanName, value就是BeanDefinition

這也是迄今為止我們遇到的第一個map, 這個map是BeanFactory的一個組件,但是它可不是傳說中的IOC容器,大家也看到了它里面存放的是BeanDefinition,而不是Bean

將配置類注冊進BeanFactory

回到一開始AnnotationConfigApplicationContextregister(annotatedClasses);方法,然后一路往下跟,會經過幾個沒有什么重要邏輯的方法, 然后來到這里

public void register(Class<?>... annotatedClasses) {
    for (Class<?> annotatedClass : annotatedClasses) {
        //  繼續跟進去
        registerBean(annotatedClass);
    }
}

通過上面的代碼,我們可以回想,annotatedClasses這個可變長度的參數,其實就是我們在AnnotationConfigApplicationContext中傳遞進來的主配置類MainConfig, 也就是說,這個主配置類是可以存在多個的

接著往下跟

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
            @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
        // 可以將當前類理解成一個方便參數傳遞的封裝類
        // 意為: 被加上注解的通用的BD
        // 將傳遞進來的 主配置類封裝進 這個AnnotatedGenericBeanDefinition
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);

        if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
            return;
        }

        abd.setInstanceSupplier(instanceSupplier);

        // 解析出它的元數據
        ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
        // 設置它的作用域
        abd.setScope(scopeMetadata.getScopeName());
        // 名稱生成器, 目的是為BeanDefinition取個名字,因為這個BD最終被存放到一個map中,
        // 默認情況下@Configuration(value = "XXX") 這個value有值,就是使用這個當成名字
        // 都這就使用 類名首字母小寫當成名字
        String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));

        // 處理bean上的通用注解, @Lazy  @Dependon @Primary role等
        AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);

        if (qualifiers != null) {
            for (Class<? extends Annotation> qualifier : qualifiers) {
 
                if (Primary.class == qualifier) {
                    abd.setPrimary(true);
                }
                //懶加載,前面加過
                else if (Lazy.class == qualifier) {
                    abd.setLazyInit(true);
                }
                else {
            
                    abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                }
            }
        }

        for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
            customizer.customize(abd);
        }
        // 理解成方便參數傳遞的封裝類
        BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd,beanName);
  
        definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
        // 我們關注的重點, 注冊BeanDefinition
        BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
    }

上面的函數的主要作用如下: 將我們通過AnnotationConfigApplicationContext構造函數傳遞進來的主配置類封裝進了AnnotatedGenericBeanDefinition中,然后解析它身上的其他注解完成屬性的賦值

接著跟進registerBeanDefinition()方法

    public static void registerBeanDefinition(
            BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
            throws BeanDefinitionStoreException {

        //   再來這個方法之前封裝了一個 difinitionHolder , 然后在這里又把它拆分開傳遞給了下面的函數
        // Register bean definition under primary name.
        String beanName = definitionHolder.getBeanName();
        //   在當前的BeanDefinitionReaderUtils中使用
        registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

        // Register aliases for bean name, if any.
        String[] aliases = definitionHolder.getAliases();
        if (aliases != null) {
            for (String alias : aliases) {
                registry.registerAlias(beanName, alias);
            }
        }
    }

繼續跟進

    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

于是有回到了上面注冊6大RootBeanDefinition的邏輯中,將我們的主配置類注冊進BeanFactoryBeanDefinitionMap

未完待續...

posted @ 2019-10-14 22:34  賜我白日夢  閱讀(...)  評論(... 編輯 收藏
ag二分彩