IOC 啟動流程

CyrusHuang發表於2024-10-25

初始化12步驟

容器建立會進入 refresh 方法,總共 12 個步驟

// org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

        // 步驟一:準備階段
        prepareRefresh();

        // 步驟二:獲得一個 BeanFactory(bean 定義資訊在這一步會儲存好)
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // 步驟三:給 BeanFactory 賦能
        prepareBeanFactory(beanFactory);

        try {
            // 步驟四:擴充套件 BeanFactory(這是個鉤子方法,目的是留給子類的,子類可根據需要再次賦予 BeanFactory 更多能力)
            postProcessBeanFactory(beanFactory);

            StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
            
            // 步驟五:執行 BeanFactoryProPercessor
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory);
            beanPostProcess.end();

            // Initialize message source for this context.
            initMessageSource();

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            onRefresh();

            // Check for listener beans and register them.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            finishRefresh();
        }
		...
    }
}

步驟1:準備容器

// org.springframework.context.support.AbstractApplicationContext#prepareRefresh
protected void prepareRefresh() {
    // 計時
    this.startupDate = System.currentTimeMillis();
    this.closed.set(false);
    this.active.set(true);

    // 這是一個模板方法,子類複寫自定義配置 spring 資訊,MVC、Boot、Cloud 等很多框架都複寫過
    initPropertySources();

    // 必要引數驗證
    getEnvironment().validateRequiredProperties();

    // 初始化事件監聽器和事件,都置為空列表
    if (this.earlyApplicationListeners == null) {
        this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
    }
    else {
        this.applicationListeners.clear();
        this.applicationListeners.addAll(this.earlyApplicationListeners);
    }
    this.earlyApplicationEvents = new LinkedHashSet<>();
}

步驟2:獲得 BeanFactory

  • 產生一個新鮮的 BeanFactory
  • 儲存好 bean 定義資訊

ApplicationContext 一般叫容器,BeanFactory 是真正儲存 bean 的地方

// org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    return getBeanFactory();
}

// org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        // 這裡會把 bean 定義資訊準備好
        loadBeanDefinitions(beanFactory);
        this.beanFactory = beanFactory;
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

步驟3:初始化 BeanFactory

上一步剛初始化了 BeanFactory,還沒什麼能力,這一步是配置 BeanFactory 的屬性,讓其具有處理某些動作的能力

當遇到相關動作,就會使用這裡賦予的能力,所以這裡程式碼比較簡單,就是給不同屬性賦值

  • 比如 addBeanPostProcessor 給 BeanFactory 新增了一些後置處理器
    • 加入到 beanPostProcessors 屬性中
    • 比如 SPEL 解析器,各種 Aware 回撥處理器
  • 比如 ignoreDependencyInterface 忽略了一些自動裝配的類
    • 加入到 ignoredDependencyInterfaces 屬性中
    • 1,這些介面的實現類的屬性@Autowired 不生效(不能注入別的 bean)
    • 2,別的 bean 裡也使用 @Autowired 給屬性賦值也不生效(不能被別的 bean 注入)
  • 比如 registerResolvableDependency 提前放入一些可能需要別的依賴的 bean
    • 是加入到 resolvableDependencies 屬性中
    • 這一步是為了提升效率的,如果不提前放,後面找到這些 bean 也會放進去(事先就放進去)
// org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    // 類載入器
    beanFactory.setBeanClassLoader(getClassLoader());
    
    // 是否不解析 SPEL,spring.spel.ignore 配置項來控制
    if (!shouldIgnoreSpel) { 
        // StandardBeanExpressionResolver:SPEL 表示式解析器
        beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
    }
    
    // ResourceEditorRegistrar:用於把配置檔案轉成一個 Resource 物件
    beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

    // 新增後置處理器,如果有 bean 實現了 ApplicationContextAware,BeanFactory 使用 ApplicationContextAwareProcessor 去處理
    beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    
    // 忽略一些自動裝配
    beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
    beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
    beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
    beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
    beanFactory.ignoreDependencyInterface(ApplicationStartupAware.class);

    // 這些註冊為 bean,比如可以直接 @Autorired BeanFactory beanFactory 來注入 BeanFactory
    beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
    beanFactory.registerResolvableDependency(ResourceLoader.class, this);
    beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
    beanFactory.registerResolvableDependency(ApplicationContext.class, this);

    // 新增後置處理器,讓 BeanFactory 可以處理時間釋出與監聽
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

    // GraalVM 支援,java 虛擬機器一般都是 hotspot VM
    if (!NativeDetector.inNativeImage() && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }

    // 再實現註冊一些預設的 bean
    if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
    }
    if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
        beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
    }
    if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
        beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
    }
}

步驟4:擴充套件 BeanFactory

上一步已經賦能了,這裡再次賦能,這是一個鉤子方法,沒有實現,所以專門提供給子類的

比如 SpringMVC 擴充套件後我們標註 @Controller 就會把這個 bean 注入到容器中

步驟5:執行 BeanFactoryPostProcesser

步驟 3 給 BeanFactory 放入了一批後置處理器,這一步就是要執行他們

// org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // this.getBeanFactoryPostProcessors() 就是獲取所有 bean 工廠後置處理器,此時是空的 invokeBeanFactoryPostProcessors 會去找
    // invokeBeanFactoryPostProcessors 首先找到所有實現了 BeanFactoryPostProcessor 介面的 bean,然後挨個呼叫其 postProcessBeanFactory 方法
    // BeanFactoryPostProcessor 幹嘛的?修改 bean 定義的,在建立前對 bean 定義做一些修改,後續根據修改後的定義來建立 bean
    PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, this.getBeanFactoryPostProcessors());
    // GraalVM 支援
    if (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean("loadTimeWeaver")) {
        beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
        beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
    }
}

// org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
public static void invokeBeanFactoryPostProcessors(
        ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
    ...
    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
        }
        else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            // 找到所有實現了 BeanFactoryPostProcessor 的類
            priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }
    ...
}

相關文章