SpringBoot 啓動流程

SpringBoot 啓動流程

  • 加載 resources/META-INF/spring.factories 中配置的 ApplicationContextInitializer 和 ApplicationListener。
/**
 *  加載在框架內部使用的各種通用工廠 bean。
 *  spring.factories 文件必須滿足 Properties 文件格式,屬性的 key 是接口或抽象類的全限定類名,
 *  value 是一組由逗號分隔的實現類全類名。
 */
public final class SpringFactoriesLoader {
    /**
     *  工廠 bean 的搜索路徑,可以在多個 jar 文件中出現 spring.factories 文件。
     */
    public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";

    private static final Log logger = LogFactory.getLog(SpringFactoriesLoader.class);

    private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();

    private SpringFactoriesLoader() {
    }

    /**
     *  使用給定的類加載器,加載並實例化目標路徑 FACTORIES_RESOURCE_LOCATION 下特定接口的實現類,
     *  或抽象類的子類。創建的類實例根據 AnnotationAwareOrderComparator 進行排序。
     */
    public static <T> List<T> loadFactories(Class<T> factoryClass, @Nullable ClassLoader classLoader) {
        Assert.notNull(factoryClass, "'factoryClass' must not be null");
        ClassLoader classLoaderToUse = classLoader;
        if (classLoaderToUse == null) {
            classLoaderToUse = SpringFactoriesLoader.class.getClassLoader();
        }
        final List<String> factoryNames = loadFactoryNames(factoryClass, classLoaderToUse);
        if (logger.isTraceEnabled()) {
            logger.trace("Loaded [" + factoryClass.getName() + "] names: " + factoryNames);
        }
        final List<T> result = new ArrayList<>(factoryNames.size());
        for (final String factoryName : factoryNames) {
            result.add(instantiateFactory(factoryName, factoryClass, classLoaderToUse));
        }
        AnnotationAwareOrderComparator.sort(result);
        return result;
    }

    /**
     *  使用指定的類加載器,加載 FACTORIES_RESOURCE_LOCATION 路徑下指定類型的 factory 全類名。
     */
    public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
        // 獲取目標 factory 全類名
        final String factoryClassName = factoryClass.getName();
        // 加載所有配置文件,並讀取指定 factory 的實現類列表
        return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
    }

    private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
        // 如果已經加載了 spring.factories 文件,則直接從緩存中獲取
        MultiValueMap<String, String> result = cache.get(classLoader);
        if (result != null) {
            return result;
        }

        try {
            // 讀取資源 URL
            final Enumeration<URL> urls = classLoader != null ?
                    classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
                        ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION);
                    result = new LinkedMultiValueMap<>();
                    while (urls.hasMoreElements()) {
                        final URL url = urls.nextElement();
                        final UrlResource resource = new UrlResource(url);
                        // 將資源加載到 Properties 文件中
                        final Properties properties = PropertiesLoaderUtils.loadProperties(resource);
                        for (final Map.Entry<?, ?> entry : properties.entrySet()) {
                            // 提取 factory 類名稱作爲 key
                            final String factoryClassName = ((String) entry.getKey()).trim();
                            /**
                             *  將配置的實現類按照 , 分隔,添加到 LinkedMultiValueMap 中。
                             *  內部通過 LinkedList 管理相同 factory 名稱的各種實現類。
                             */
                            for (final String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
                                result.add(factoryClassName, factoryName.trim());
                            }
                        }
                    }
                    // 加入緩存
                    cache.put(classLoader, result);
                    return result;
        }
        catch (final IOException ex) {
            throw new IllegalArgumentException("Unable to load factories from location [" +
                    FACTORIES_RESOURCE_LOCATION + "]", ex);
        }
    }

    @SuppressWarnings("unchecked")
    private static <T> T instantiateFactory(String instanceClassName, Class<T> factoryClass, ClassLoader classLoader) {
        try {
            final Class<?> instanceClass = ClassUtils.forName(instanceClassName, classLoader);
            if (!factoryClass.isAssignableFrom(instanceClass)) {
                throw new IllegalArgumentException(
                        "Class [" + instanceClassName + "] is not assignable to [" + factoryClass.getName() + "]");
            }
            return (T) ReflectionUtils.accessibleConstructor(instanceClass).newInstance();
        }
        catch (final Throwable ex) {
            throw new IllegalArgumentException("Unable to instantiate factory class: " + factoryClass.getName(), ex);
        }
    }

}
  • 加載 resources/META-INF/spring.factories 中配置的 SpringApplicationRunListener
/**
 *  SpringApplication 監聽器,必須提供一個接受命令行參數 String[] 的
 *  public 構造函數完成實例的初始化。
 */
public interface SpringApplicationRunListener {

    /**
     *  1)加載完 SpringApplicationRunListener 實例後立即執行的方法,在 Application 初始化早期使用。
     */
    void starting();

    /**
     *  2)environment 準備好時調用,在 ApplicationContext 創建之前。
     */
    void environmentPrepared(ConfigurableEnvironment environment);

    /**
     *  3)在 ApplicationContext 創建並準備好時調用,此時資源還未加載。
     */
    void contextPrepared(ConfigurableApplicationContext context);

    /**
     *  4)ApplicationContext 加載完成之後調用,但是 ApplicationContext 還未刷新。
     *  組件掃描還未執行,BeanDefinition 還未註冊。
     */
    void contextLoaded(ConfigurableApplicationContext context);

    /**
     *  5)ApplicationContext 已經刷新並啓動,但還未執行 CommandLineRunner 和 ApplicationRunner。
     */
    void started(ConfigurableApplicationContext context);

    /**
     *  6)ApplicationContext 已經刷新並啓動,所有的CommandLineRunner 和 ApplicationRunner 都已經執行。
     */
    void running(ConfigurableApplicationContext context);

    /**
     *  運行此 ApplicationContext 過程中出現異常
     */
    void failed(ConfigurableApplicationContext context, Throwable exception);
}

/**
 *  用於發佈 SpringApplicationEvent 的 SpringApplicationRunListener
 */
public class EventPublishingRunListener implements SpringApplicationRunListener, Ordered {
    /**
     *  目標應用程序
     */
    private final SpringApplication application;

    /**
     *  命令行參數
     */
    private final String[] args;

    /**
     *  簡單的應用事件廣播器
     */
    private final SimpleApplicationEventMulticaster initialMulticaster;

    public EventPublishingRunListener(SpringApplication application, String[] args) {
        this.application = application;
        this.args = args;
        initialMulticaster = new SimpleApplicationEventMulticaster();
        for (final ApplicationListener<?> listener : application.getListeners()) {
            initialMulticaster.addApplicationListener(listener);
        }
    }

    @Override
    public int getOrder() {
        return 0;
    }

    @Override
    public void starting() {
        initialMulticaster.multicastEvent(
                new ApplicationStartingEvent(application, args));
    }

    @Override
    public void environmentPrepared(ConfigurableEnvironment environment) {
        initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
                application, args, environment));
    }

    @Override
    public void contextPrepared(ConfigurableApplicationContext context) {
        initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
                application, args, context));
    }

    @Override
    public void contextLoaded(ConfigurableApplicationContext context) {
        for (final ApplicationListener<?> listener : application.getListeners()) {
            if (listener instanceof ApplicationContextAware) {
                ((ApplicationContextAware) listener).setApplicationContext(context);
            }
            context.addApplicationListener(listener);
        }
        initialMulticaster.multicastEvent(
                new ApplicationPreparedEvent(application, args, context));
    }

    @Override
    public void started(ConfigurableApplicationContext context) {
        context.publishEvent(
                new ApplicationStartedEvent(application, args, context));
    }

    @Override
    public void running(ConfigurableApplicationContext context) {
        context.publishEvent(
                new ApplicationReadyEvent(application, args, context));
    }

    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) {
        final ApplicationFailedEvent event = new ApplicationFailedEvent(application,
                args, context, exception);
        if (context != null && context.isActive()) {
            // Listeners have been registered to the application context so we should
            // use it at this point if we can
            context.publishEvent(event);
        }
        else {
            // An inactive context may not have a multicaster so we use our multicaster to
            // call all of the context's listeners instead
            if (context instanceof AbstractApplicationContext) {
                for (final ApplicationListener<?> listener : ((AbstractApplicationContext) context)
                        .getApplicationListeners()) {
                    initialMulticaster.addApplicationListener(listener);
                }
            }
            initialMulticaster.setErrorHandler(new LoggingErrorHandler());
            initialMulticaster.multicastEvent(event);
        }
    }

    private static class LoggingErrorHandler implements ErrorHandler {
        private static Log logger = LogFactory.getLog(EventPublishingRunListener.class);

        @Override
        public void handleError(Throwable throwable) {
            logger.warn("Error calling ApplicationEventListener", throwable);
        }
    }
}
  • 創建 StandardServletEnvironment 並完成初始配置。
1)寫入轉換服務 ApplicationConversionService.getSharedInstance()
2)將命令行參數作爲屬性源加入到 environment.getPropertySources() 中
3)寫入配置的 AdditionalProfile。
  • 通過 EventPublishingRunListener 發佈 ApplicationEnvironmentPreparedEvent 事件

  • 加載 resources/META-INF/spring.factories 中配置的 EnvironmentPostProcessor,
    並觸發其 postProcessEnvironment 調用,完成 Environment 的後處理【主要用於加載屬性源到 Environment 中】。

  • 將 Environment 綁定到 SpringApplication 中。

  • 創建 ApplicationContext:AnnotationConfigServletWebServerApplicationContext

  • 加載 resources/META-INF/spring.factories 中配置的 SpringBootExceptionReporter【FailureAnalyzers】

  • 執行所有已加載的 ApplicationContextInitializer,附加自定義配置。

  • 通過 EventPublishingRunListener 發佈 ApplicationContextInitializedEvent 事件

  • 創建 BeanDefinitionLoader,將應用程序主類解析爲 BeanDefinition 並註冊到 DefaultListableBeanFactory 中。
@Lazy:此 Bean 是否延遲初始化
@DependsOn:此 Bean 是否需要依賴其他 Bean
@Role:此 Bean 的組件角色
@Description:此 Bean 的描述信息
@Scope:bean 的代理默認和作用域
@Primary:依賴注入時存在多個候選 bean 時,優先注入此 bean
  • 通過 EventPublishingRunListener 發佈 ApplicationPreparedEvent 事件。

刷新此 ApplicationContext: AbstractApplicationContext#refresh()

AbstractApplicationContext#
    @Override
    public void refresh() throws BeansException, IllegalStateException {
        synchronized (startupShutdownMonitor) {
            // 1)準備刷新上下文
            prepareRefresh();

            // 2)通知子類刷新內部的 ConfigurableListableBeanFactory
            final ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

            // 3)準備在此 ApplicationContext 中使用的 BeanFactory
            prepareBeanFactory(beanFactory);

            try {
                // 4)允許在 ApplicationContext 中對 BeanFactory 進行後處理
                postProcessBeanFactory(beanFactory);

                // 5)執行註冊在當前 ApplicationContext 中的 beanFactory 後處理器
                invokeBeanFactoryPostProcessors(beanFactory);

                // 6)將 BeanPostProcessor 註冊到容器中
                registerBeanPostProcessors(beanFactory);

                // 7)初始化 MessageSource
                initMessageSource();

                // 8)初始化 SimpleApplicationEventMulticaster,用於實現事件發佈
                initApplicationEventMulticaster();

                // 9)初始化其他特殊的 bean
                onRefresh();

                // 10)註冊 ApplicationListener
                registerListeners();

                // 11)實例化所有非延遲的單例類
                finishBeanFactoryInitialization(beanFactory);

                // 12)清理資源緩存,初始化 LifecycleProcessor,併發布相關事件
                finishRefresh();
            }

            catch (final BeansException ex) {
                if (logger.isWarnEnabled()) {
                    logger.warn("Exception encountered during context initialization - " +
                            "cancelling refresh attempt: " + ex);
                }

                // 13)刪除已經實例化的單例,避免資源泄漏
                destroyBeans();

                // 14)設置 active 標識
                cancelRefresh(ex);

                // 15)傳播異常到外部
                throw ex;
            }

            finally {
                // 16)重設通用的緩存
                resetCommonCaches();
            }
        }
    }
  • prepareRefresh:清除類路徑掃描器緩存、寫入 closed、active 標識、驗證所有必須的屬性是否都能解析。

  • obtainFreshBeanFactory:寫入 refreshed 標識,獲取 DefaultListableBeanFactory。

  • prepareBeanFactory:寫入 BeanPostProcessor、寫入可以忽略的依賴注入接口,註冊部分內部可解析的依賴接口等。

  • postProcessBeanFactory:註冊 WebApplicationScope,註冊部分內部可解析的依賴接口。

  • invokeBeanFactoryPostProcessors:
    執行 SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor
    註冊用於獲取 MetadataReader 的 org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory 的 BeanDefinition。
實例化並執行所有的 BeanDefinitionRegistryPostProcessor【內部只註冊了 ConfigurationClassPostProcessor】:
1)執行所有實現 PriorityOrdered 接口的 BeanDefinitionRegistry 後處理器【可以通過自定義 ApplicationContextInitializer 註冊】。
    實例化並註冊用於解析配置類的解析器【ConfigurationClassPostProcessor】:org.springframework.context.annotation.internalConfigurationAnnotationProcessor。
    使用 ConfigurationClassParser 解析主配置類並執行 ComponentScan、執行自動配置類的解析、各種導入 XML 文件的解析,將相關所有類的 BeanDefinition 
    註冊到 DefaultListableBeanFactory 中。
2)執行所有實現 Ordered 接口的 BeanDefinitionRegistry 後處理器。
3)執行所有普通的 BeanDefinitionRegistry 後處理器。
1)實例化並順序執行以下內置的 BeanFactoryPostProcessor 後處理器
無操作:org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer$CachingMetadataReaderFactoryPostProcessor
無操作:org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer$ConfigurationWarningsPostProcessor
使用 ConfigurationClassEnhancer 強化所有的配置類:org.springframework.context.annotation.ConfigurationClassPostProcessor
org.springframework.boot.context.config.ConfigFileApplicationListener$PropertySourceOrderingPostProcessor
2)
執行實現 PriorityOrdered 接口的 BeanFactoryPostProcessor 後處理器。
執行實現 Ordered 接口的 BeanFactoryPostProcessor 後處理器。
執行普通的 BeanFactoryPostProcessor 後處理器。
  • registerBeanPostProcessors:
    按照 【PriorityOrdered、Ordered、普通】的順序將 BeanPostProcessor 添加到 BeanFactory 中。
org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.boot.web.servlet.context.WebApplicationContextServletContextAwareProcessor org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor
org.springframework.context.support.PostProcessorRegistrationDelegate$BeanPostProcessorChecker
org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator
org.springframework.validation.beanvalidation.MethodValidationPostProcessor
org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor
org.springframework.boot.web.server.WebServerFactoryCustomizerBeanPostProcessor
org.springframework.boot.web.server.ErrorPageRegistrarBeanPostProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
org.springframework.context.support.ApplicationListenerDetector
  • initMessageSource:註冊 messageSource 單例【DelegatingMessageSource】

  • 註冊 applicationEventMulticaster 單例【SimpleApplicationEventMulticaster】,用於廣播 ApplicationEvent。

  • onRefresh:設置主題,創建內嵌服務器【WebServer】,獲取 ServletContextInitializer【DispatcherServletRegistrationBean】
    初始化器並註冊 DispatcherServlet 到 javax.servlet.ServletContext 和 org.apache.catalina.core.ApplicationContext 中。
    註冊 OrderedCharacterEncodingFilter、OrderedHiddenHttpMethodFilter、OrderedFormContentFilter、OrderedRequestContextFilter
    等過濾器,也可註冊自定義過濾器。
    寫入 ServletContextPropertySource、ServletConfigPropertySource 到 Environment 中。

  • registerListeners:註冊內置的 ApplicationListener、自定義的 ApplicationListener 到 ApplicationEventMulticaster 中。

  • finishBeanFactoryInitialization:凍結 DefaultListableBeanFactory 中註冊的 BeanDefinition 信息,並實例化所有非延遲初始化的單例 bean。
    在所有 eager 單例初始化完成之後,如果其實現了 SmartInitializingSingleton 接口,則觸發其 afterSingletonsInstantiated 調用完成後處理。
bean 的實例化過程:
1)優先實例化所有其依賴的 bean
2)執行 InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation 預處理,
如果該方法手動創建了 bean,則直接返回,不進入框架創建 bean 的主流程。
3)實例化 bean
4)執行 MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition 後處理,
AutowiredAnnotationBeanPostProcessor:解析 @Autowired、@Value、@Inject【JSR303】 註解元數據並緩存。
CommonAnnotationBeanPostProcessor:解析 @PostConstruct、@PreDestroy 註解並將目標方法加入 BeanDefinition 中,解析 @Resource 註解元數據並緩存。
5)將此 bean 加入到 singletonFactories 緩存中,以解決循環依賴問題。
6)執行 InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation 後處理,
如果該方法完成了 bean 的依賴屬性注入並返回 false,則跳過框架的屬性注入流程。
7)執行 InstantiationAwareBeanPostProcessor#postProcessProperties 依賴屬性注入【直接屬性注入、set 方法注入】。
@Resource、@Autowired、@Value、@Inject【JSR303】
8)執行其他方式的屬性依賴注入,如 XML 配置方式。
9)執行 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 注入。
10)觸發 BeanPostProcessor#postProcessBeforeInitialization 調用,
ApplicationContextAwareProcessor:EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware 注入。
ServletContextAwareProcessor:ServletContextAware、ServletConfigAware 注入。
11)執行 InitializingBean#afterPropertiesSet 調用,執行自定義的初始化方法。
12)執行 BeanPostProcessor#postProcessAfterInitialization 調用。
AnnotationAwareAspectJAutoProxyCreator:目標類型上存在 AspectJ 切面註解、目標類型能匹配 Spring 內置的 Advisor【緩存通知、事務處理】,則爲目標 bean 創建代理。
MethodValidationPostProcessor:目標類型上存在 @Validated 註解,方法參數或返回類型上存在 JSR303 校驗約束,則爲目標 bean 創建代理。
PersistenceExceptionTranslationPostProcessor:如果目標類型實現了 org.springframework.dao.support.PersistenceExceptionTranslator 接口,
則將本地資源異常轉換爲 DataAccessException。
ApplicationListenerDetector:目標 bean 實現了 ApplicationListener 接口,則將其加入到 AbstractApplicationContext.applicationListeners 中。
  • 註冊 DefaultLifecycleProcessor,查找所有實現 SmartLifecycle 接口的 bean && 如果它是 isAutoStartup(),則觸發其 start() 方法調用。

  • 通過 EventPublishingRunListener 發佈 ContextRefreshedEvent 事件。

  • 啓動 WebServer。

  • 通過 EventPublishingRunListener 發佈 ServletWebServerInitializedEvent 事件。

  • 清理各種緩存
ReflectionUtils.clearCache();
AnnotationUtils.clearCache();
ResolvableType.clearCache();
CachedIntrospectionResults.clearClassLoader(getClassLoader());
  • 註冊 Application 的 ShutdownHook。

  • 觸發 SpringApplicationRunListener 的 started 通知。

  • 通過 EventPublishingRunListener 發佈 ApplicationStartedEvent 事件。

  • 按照 Order 對 ApplicationRunner、CommandLineRunner 進行排序,並順序執行。

  • 觸發 SpringApplicationRunListener 的 running 通知。

  • 通過 EventPublishingRunListener 發佈 ApplicationReadyEvent 事件。

  • 應用程序啓動完成。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章