天天看點

Spring5源碼分析------bean的生命周期(一)

1.BeanFactory和ApplicationContext

我們先檢視ApplicationContext的類圖吧(IDEA快捷鍵Ctrl+Alt+U)

Spring5源碼分析------bean的生命周期(一)

我們會發現BeanFactory是Application的父類,那麼他們兩者有什麼差別呢

我們先來了解他們的作用

BeanFactory:

是Spring裡面最低層的接口,提供了最簡單的容器的功能,隻提供了執行個體化對象和拿對象的功能;

ApplicationContext:

應用上下文,繼承BeanFactory所有的功能,它是Spring的一各更進階的容器,提供了更多的有用的功能;

  1. 國際化(MessageSource)
  2. 通路資源,如URL和檔案(ResourceLoader)
  3. 載入多個(有繼承關系)上下文 ,使得每一個上下文都專注于一個特定的層次,比如應用的web層
  4. 消息發送、響應機制(ApplicationEventPublisher)
  5. AOP(攔截器)

兩者裝載bean的差別

BeanFactory:

BeanFactory在啟動的時候不會去執行個體化Bean,中有從容器中拿Bean的時候才會去執行個體化;

ApplicationContext:

ApplicationContext在啟動的時候就把所有的Bean全部執行個體化了。

延遲執行個體化的優點:(BeanFactory)

應用啟動的時候占用資源很少;對資源要求較高的應用,比較有優勢;

不延遲執行個體化的優點: (ApplicationContext)

  1. 所有的Bean在啟動的時候都加載,系統運作的速度快;
  2. 在啟動的時候所有的Bean都加載了,我們就能在系統啟動的時候,盡早的發現系統中的配置問題
  3. 建議web應用,在啟動的時候就把所有的Bean都加載了。

2.AnnotationConfig啟動方式解析

建立MyConfig.java

import org.springframework.context.annotation.Configuration;

@Configuration
public class MyConfig {
}
           

Application.java

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContextExtensionsKt;

public class Application {
    public static void main(String[] args) {
//        ApplicationContext
        new AnnotationConfigApplicationContext(MyConfig.class);
    }
}
           

源碼檢視AnnotationConfigApplicationContext

Spring5源碼分析------bean的生命周期(一)

進入的此詞方法,說明我們啟動需要先經過這三個方法,我們先來看this(),點選檢視

Spring5源碼分析------bean的生命周期(一)

跳轉到無參構造中來,但是,我們看方法必須要先看類,看他是否有繼承(這點很重要,因為作為子類,執行之前都得先執行父類),是以跳轉過來,我們會發現AnnotationConfigApplicationContext繼承了GenericApplicationContext。

Spring5源碼分析------bean的生命周期(一)

這個很重要,後面我們會用到

好了,我們再次回到this.reader,this.scanner。他們兩個很好了解,一個是讀取(注解),一個是掃描(掃包)

this()看完了,

接下來看this.register(annotatedClasses)

Spring5源碼分析------bean的生命周期(一)
Spring5源碼分析------bean的生命周期(一)
Spring5源碼分析------bean的生命周期(一)

好了,終于到頭了

<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
		// 我們之前學習過RootBeanDefinition,它是用于傳統方式往IOC容器注入bean
		// 一樣的 AnnotatedGenericBeanDefinition 屬于注解方式注入bean
        AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
        // 判斷是否使用condition 條件注冊
        if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
        	// 用于建立bean執行個體的回調
            abd.setInstanceSupplier(instanceSupplier);
            // 解析bean作用域(單例或者原型),如果有@Scope注解,則解析@Scope,沒有則預設為singleton
            ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
            // 作用域寫回BeanDefinition資料結構, abd中缺損的情況下為空,将預設值singleton重新指派到abd
            abd.setScope(scopeMetadata.getScopeName());
            // 生成bean配置類beanName
            String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
            // 通用注解解析到abd結構中,主要是處理Lazy, primary DependsOn, Role ,Description這五個注解
            AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
            int var10;
            int var11;
            // @Qualifier特殊限定符處理,@Qualifier 除了bean類級别的限定符之外,要考慮的限定符特定限定符注釋
            if (qualifiers != null) {
                Class[] var9 = qualifiers;
                var10 = qualifiers.length;

                for(var11 = 0; var11 < var10; ++var11) {
                    Class<? extends Annotation> qualifier = var9[var11];
                    if (Primary.class == qualifier) {
                        // 如果配置@Primary注解,則設定目前Bean為自動裝配autowire時首選bean
                        abd.setPrimary(true);
                    } else if (Lazy.class == qualifier) {
                        // 設定目前bean為延遲加載
                        abd.setLazyInit(true);
                    } else {
                        // //其他注解,則添加到abd結構中
                        abd.addQualifier(new AutowireCandidateQualifier(qualifier));
                    }
                }
            }
            
            BeanDefinitionCustomizer[] var13 = definitionCustomizers;
            var10 = definitionCustomizers.length;
            // 自定義bean注冊,通常用在applicationContext建立後,手動向容器中一lambda表達式的方式注冊bean
            for(var11 = 0; var11 < var10; ++var11) {
                BeanDefinitionCustomizer customizer = var13[var11];
                // //自定義bean添加到BeanDefinition
                customizer.customize(abd);
            }
            // 根據beanName和bean定義資訊封裝一個beanHolder,beanHolder其實就是一個 beanname和BeanDefinition的映射
            BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
            // 根據注解Bean定義類中配置的作用域@Scope注解的值,為Bean定義應用相應的代理模式
            definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
            // 按名稱将bean定義資訊注冊到容器中,實際上DefaultListableBeanFactory内部維護一個Map<String, BeanDefinition>類型變量beanDefinitionMap beanDefinitionMap用來儲存beanName,BeanDefinition
            BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
        }
    }
           

register方法重點完成了bean配置類本身的基本資訊注冊

接下來看this.refresh()

----後期補充-----