1. 程式人生 > 其它 >Spring原始碼閱讀 - 基礎流程

Spring原始碼閱讀 - 基礎流程

1. AnnotationConfigApplicationContext 的 reader 和 scanner

public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
    this();
    // 註冊解析這個 Bean 為 BeanDefinition
    register(componentClasses);
    // 重新整理容器,這個時候才是對這個 BeanDefinition 進行進一步解析
    refresh();
}
public AnnotationConfigApplicationContext() {
    this.reader = new AnnotatedBeanDefinitionReader(this);
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

內部邏輯先暫略,簡略描述

/**
 * 註解 Class 讀取器/處理器,在建構函式中建立
 * AnnotatedBeanDefinitionReader 被例項化時已經向容器注入了部分 BeanDefinition
 * 區分 BeanPostProcessor 和 BeanFactoryPostProcessor
 *
 * 從其提供的 API 來看,大致就是將一個 Class 解析為 BeanDefinition 放入 BeanFactory
 */
private final AnnotatedBeanDefinitionReader reader;

/**
 * 類路徑掃描器,可以進行包掃描,然後呢?
 * 這個在例項化時就沒有建立預先注入 BeanDefinition 了
 */
private final ClassPathBeanDefinitionScanner scanner;

2. register

利用 reader 解析傳入的 Class 並進行基礎的解析轉換為 BeanDefinition 並將這個 BeanDefinition 注入 BeanFactory
org.springframework.context.annotation.AnnotationConfigApplicationContext#register

public void register(Class<?>... componentClasses) {
    Assert.notEmpty(componentClasses, "At least one component class must be specified");
    // 使用註解BD讀取器去註冊/處理這個 Bean
    this.reader.register(componentClasses);
}

org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register

public void register(Class<?>... componentClasses) {
    for (Class<?> componentClass : componentClasses) {
        registerBean(componentClass);
    }
}

public void registerBean(Class<?> beanClass) {
    doRegisterBean(beanClass, null, null, null, null);
}

private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
        @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
        @Nullable BeanDefinitionCustomizer[] customizers) {

    // Generic [dʒəˈnerɪk],通用的,adj. (藥物或商品)無專利的,未註冊的
    // 這個應該是用於封裝一個(可能)使用了註解的Bean,內部會進行解析註解資訊並封裝
    // 封裝為 BeanDefinition
    AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
    // 這個應該是涉及到條件注入等的
    if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        return;
    }

    // 下面解析註解並設定 BeanDefinition,從上面的 new AnnotatedGenericBeanDefinition 可以看到只是將解析的註解封裝為一個屬性,具體
    //    如何處理這些註解並設定 BeanDefinition 則由後面的進行解析

    // 這個是不由 Spring 例項化,表示由這個 supplier 進行例項化,在哪裡有使用呢?
    abd.setInstanceSupplier(supplier);
    // 解析 Bean 的生命週期 Scope,這裡解析器也有幾種,Spring 自己的註解 @Scope 解析,javax.inject.Scope 的解析,略後者
    ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
    abd.setScope(scopeMetadata.getScopeName());
    // beanName 生成,如何自定義 BeanName 生成器?
    String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
    // 通用註解解析,那麼區分需要外部處理的和需要工具類處理的標準/條件是什麼?是是否可以直接進行簡單處理嗎(如上面的還需要解析器啥的)
    // @Lazy、@Primary、@DependsOn、@Role、@Description,後面兩個都沒使用過
    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));
            }
        }
    }

    // 定製處理,customizers 這種可以定製處理的(或命名)的在 Spring 中還挺多的
    if (customizers != null) {
        for (BeanDefinitionCustomizer customizer : customizers) {
            customizer.customize(abd);
        }
    }

    // 問題:這裡的 beanName 為什麼不可以設計到 BeanDefinition 裡面呢,還需要封裝一層
    BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
    // 如果當前類要被代理,代理的模式(JDK、CGLIB)
    definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
    // 註冊 BD 到容器,沒有進一步處理
    BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}

3. rerfresh.BeanFactoryPostProcessor 執行

上面已經將配置類給轉換為 BeanDefinition 注入容器了,接下來還需要解析這個 BeanDefinition
BeanFactoryPostProcessor:對 BeanDefinition 進行進一步修飾和處理,一般不會再將 BeanDefinition 注入 BeanFactory
BeanDefinitionRegistryPostProcessors:BeanFactoryPostProcessor 的子介面,主要是發現 BeanDefinition 並將 BeanDefinition 注入 BeanFactory
注意上面兩個介面所提供的/需要實現的方法的功能,一般不會在 BeanFactoryPostProcessor 介面提供的功能中發現 BD 和注入 BD

org.springframework.context.support.AbstractApplicationContext#refresh

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // Prepare this context for refreshing.
        // 暫略
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        // 暫略
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        // 內部設定了一些 BeanFactory 的屬性,直接注入了一些 Bean 例項
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            // 暫略,這裡好像 Web 進行處理了
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            // Invoke factory processors registered as beans in the context.
            // 呼叫 BeanFactoryPostProcessor 對 BeanDefinition 進行處理,通過對 BeanDefinition 處理可能又會發現更多的 BeanDefinition(如解析 @ComponentScan 時)
            invokeBeanFactoryPostProcessors(beanFactory);
            ...
        }
    }
}

上面程式碼很多都略去了,現在僅先抓住主幹,具體細節暫略
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 這種使用 Delegate 進行處理的方法, 是為了避免單個類太長 + 功能太多嗎?單一職責?有時候一些類我會命名為 Helper
    // 注意這裡的 getBeanFactoryPostProcessors, 也就是我們也可以在 refresh 容器前將自定義的 BeanFactoryPostProcess add 進入 ApplicationContext
    //    至於容器內部自己註冊進去的那些,會在內部自己發現(因為可以從傳入的 BeanFactory 中查)
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

    // Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
    // (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
    // 這裡也暫略
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

下面這個也只是大體流程,具體的 BeanFactoryPostProcessor 沒有具體解析流程
org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors

public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

    // WARNING: Although it may appear that the body of this method can be easily
    // refactored to avoid the use of multiple loops and multiple lists, the use
    // of multiple lists and multiple passes over the names of processors is
    // intentional. We must ensure that we honor the contracts for PriorityOrdered
    // and Ordered processors. Specifically, we must NOT cause processors to be
    // instantiated (via getBean() invocations) or registered in the ApplicationContext
    // in the wrong order.
    //
    // Before submitting a pull request (PR) to change this method, please review the
    // list of all declined PRs involving changes to PostProcessorRegistrationDelegate
    // to ensure that your proposal does not result in a breaking change:
    // https://github.com/spring-projects/spring-framework/issues?q=PostProcessorRegistrationDelegate+is%3Aclosed+label%3A%22status%3A+declined%22

    // Invoke BeanDefinitionRegistryPostProcessors first, if any.
    // 下面先呼叫的是 BeanDefinitionRegistryPostProcessors,這個主要是發現 BeanDefinition 並將 BeanDefinition 注入 BeanFactory
    // 而與其類似的(其父介面)為 BeanFactoryPostProcessor,這個主要是對 BeanDefinition 進行進一步修飾和處理,一般不會再將 BeanDefinition 注入 BeanFactory
    Set<String> processedBeans = new HashSet<>();

    // 這個不是 BeanFactory 繼承鏈的,而是單獨的一個介面,提供對容器 BeanDefinition 的增刪查等操作
    // 會有不是的場景嗎,後面不是就直接呼叫 BeanFactoryPostProcessor 操作 BeanDefinition 了(也即不能增刪等操作,僅能查詢並修改 BeanDefinition)
    if (beanFactory instanceof BeanDefinitionRegistry) {
        BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
        List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
        List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

        for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
            if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
                BeanDefinitionRegistryPostProcessor registryProcessor =
                        (BeanDefinitionRegistryPostProcessor) postProcessor;
                // 注意這裡就已經執行了,但是 BeanFactoryPostProcessor 介面的方法還未執行(父介面就是 BeanFactoryPostProcessor)
                // 這裡實際上就可以執行以下自己的 BeanDefinition 發現邏輯啊等等,MyBatis 實現了這個嗎?
                registryProcessor.postProcessBeanDefinitionRegistry(registry);
                // 儲存的實際是一已執行的,這種命名是否可以優化一下便於閱讀
                registryProcessors.add(registryProcessor);
            }
            else {
                // BeanFactoryPostProcessor 型別,還未執行
                regularPostProcessors.add(postProcessor);
            }
        }

        // 注意下面執行 BeanFactory 內的 BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor,因為需要例項化才能執行,所以在這裡就 getBean 了
        //    包括如果我們也注入了這些型別的,那麼也是在這裡就被 getBean 了,還可能沒經過整個生命週期,因此編寫時要注意

        // 下面就是處理 BeanFactory 中的,內含
        // 1. 上面自定義執行後注入的
        // 2. Spring 容器內部自己注入的
        // Do not initialize FactoryBeans here: We need to leave all regular beans
        // uninitialized to let the bean factory post-processors apply to them!
        // Separate between BeanDefinitionRegistryPostProcessors that implement
        // PriorityOrdered, Ordered, and the rest.
        List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

        // First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
        // 先處理 PriorityOrdered 介面的,也先執行
        String[] postProcessorNames =
                beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();

        // Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
        // 處理 Ordered 介面的
        postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
        for (String ppName : postProcessorNames) {
            if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
                currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                processedBeans.add(ppName);
            }
        }
        sortPostProcessors(currentRegistryProcessors, beanFactory);
        registryProcessors.addAll(currentRegistryProcessors);
        invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
        currentRegistryProcessors.clear();

        // Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
        // 處理其他的,內部進行了 while 處理,也即在上面執行後注入的如果未執行也會在下面執行,當然在下面執行後注入的也會被執行
        boolean reiterate = true;
        while (reiterate) {
            reiterate = false;
            postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
            for (String ppName : postProcessorNames) {
                if (!processedBeans.contains(ppName)) {
                    currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
                    processedBeans.add(ppName);
                    reiterate = true;
                }
            }
            sortPostProcessors(currentRegistryProcessors, beanFactory);
            registryProcessors.addAll(currentRegistryProcessors);
            invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
            currentRegistryProcessors.clear();
        }

        // Now, invoke the postProcessBeanFactory callback of all processors handled so far.
        // 這裡就是執行  BeanFactoryPostProcessor 介面的,優先順序也是先執行 BeanDefinitionRegistryPostProcessor 的,順序也是上面執行的順序
        invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
        // 這裡引數傳入的優先順序反而靠後了
        invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
    }

    else {
        // Invoke factory processors registered with the context instance.
        // 注意了,這裡僅執行了引數傳入的,對於 BeanFactory 內部的沒有執行
        // 當然同時由於 BeanFactory 型別的原因,認為是不可以向內注入 BeanDefinition 的,因此也沒必要 while 關心是否有新的注入
        invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
    }

    // 下面就應該處理 BeanFactory 內部的 BeanFactoryPostProcessor 介面方法了,上面雖然執行了一些,但那是 BeanDefinitionRegistryPostProcessor 型別的(BeanFactoryPostProcessor 子介面)

    // Do not initialize FactoryBeans here: We need to leave all regular beans
    // uninitialized to let the bean factory post-processors apply to them!
    // 獲取 BeanFactory 內部所有的 BeanFactoryPostProcessor,注意入參傳入的沒有
    String[] postProcessorNames =
            beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);

    // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
    // Ordered, and the rest.
    List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        // 上面已執行則略過
        if (processedBeans.contains(ppName)) {
            // skip - already processed in first phase above
        }
        // 分類且按照順序執行
        // 問題: 為什麼僅 priority 的在這裡就獲取了 Bean,而其他的後面才獲取呢(倒不是邏輯問題,而是寫的時候怎麼想的)
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

    // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
    List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String postProcessorName : orderedPostProcessorNames) {
        orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

    // Finally, invoke all other BeanFactoryPostProcessors.
    List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String postProcessorName : nonOrderedPostProcessorNames) {
        nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
    }
    invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

    // Clear cached merged bean definitions since the post-processors might have
    // modified the original metadata, e.g. replacing placeholders in values...
    beanFactory.clearMetadataCache();
}