Spring Boot啟動流程


基礎准備

1,BeanPostProcessor:這個接口的作用在於對於新構造的實例可以做一些自定義的修改。比如如何構造、屬性值的修改、構造器的選擇等等

2,BeanFactoryPostProcessor:在容器實例化任何其它bean之前讀取配置元數據,並可以根據需要進行修改,例如可以把bean的scope從singleton改為prototype,也可以把property的值給修改掉

3,BeanDefinitionRegistryPostProcessor:允許在普通的BeanFactoryPostProcessor接口實現類執行之前注冊更多的BeanDefinition。特別地是,BeanDefinitionRegistryPostProcessor可以注冊BeanFactoryPostProcessor的BeanDefinition

4,Import:通過注解導入BeanDefinition,例如EnableAutoConfiguration導入spring.factories配置的各種配置類。在ImportSelector中選擇要導入的Configuration類或者通過ImportBeanDefinitionRegistrar添加BeanDefinition,基於注解的導入可以通過配置屬性值決定導入那些類

應用初始化

@Configuration
@EnableAutoConfiguration//三個注解的使用后面ConfigurationClassPostProcessor部分會講到
@ComponentScan
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

  

構造SpringApplication對象

public SpringApplication(Object... sources) {
    initialize(sources);
}
private void initialize(Object[] sources) {
    // 為成員變量sources賦值
    if (sources != null && sources.length > 0) {
        this.sources.addAll(Arrays.asList(sources));
    }
    this.webEnvironment = deduceWebEnvironment();
    //從spring.factories加載ApplicationContextInitializer,用來初始化ApplicationContext,在prepareContext中調用,例如DuibaEnvironmentDecryptApplicationInitializer對配置進行解密
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //從spring.factories加載ApplicationListener,訂閱ApplicationContext的創建和刷新的不同階段的事件,被SpringApplicationRunListener調用,例如ConfigFileApplicationListener訂閱ApplicationEnvironmentPreparedEvent加載配置文件
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    this.mainApplicationClass = deduceMainApplicationClass();
}

  

圖一:默認加載的ApplicationListener以及對應的作用

核心方法

//獲取spring.factories下定義的SpringApplicationRunListener,發布SpringApplication啟動過程中的各種事件,主要是EventPublishingRunListener來將事件廣播到ApplicationListener
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//創建Environment,發布ApplicationEnvironmentPreparedEvent,springcloud就是使用BootstrapApplicationListener通過訂閱這個事件完成了configserver上配置的加載
ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
Banner printedBanner = printBanner(environment);//打印banner
//創建ApplicationContext
context = createApplicationContext();
analyzers = new FailureAnalyzers(context);
//調用ApplicationContextInitializer初始化,注入當前啟動類的BeanDefinition,完成后beanmap中還只有啟動類和AnnotationConfigUtils注入的幾個BeanPostProcessor(不考慮springcloud的場景),這個類上聲明的Configuration,EnableAutoConfiguration,ComponentScan等被ConfigurationClassPostProcessor處理加載其余的BeanDefinition
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
refreshContext(context);//核心方法,調用Context的refresh方法
afterRefresh(context, applicationArguments);
listeners.finished(context, null);

  

createApplicationContext:創建ApplicationContext 對於web應用創建AnnotationConfigEmbeddedWebApplicationContext,初始化時調用AnnotationConfigUtils.registerAnnotationConfigProcessors注冊常用的BeanPostProcessor:

ConfigurationClassPostProcessor:處理@Configuration CommonAnnotationBeanPostProcessor:處理@Resource、@PostConstruct和@PreDestroy AutowiredAnnotationBeanPostProcessor:處理@Autowired、@Value、@Lookup和@Inject注解的實現 RequiredAnnotationBeanPostProcessor:處理@Required注解 BeanValidationPostProcessor:處理@Min,@NotNull等注解

refreshContext:調用AbstractApplicationContext的refresh方法

// 初始化 refresh 的上下文環境
        prepareRefresh();
        // 初始化 BeanFactory,加載並解析BeanDefinition,子類實現
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
        // 對 BeanFactory 進行功能增強,例如添加ApplicationContextAwareProcessor設置各種Aware實現類的屬性。注入一些其它信息的bean,比如environment、systemProperties等
        //添加ApplicationListenerDetector,用於探測 ApplicationListener 類型接口
        prepareBeanFactory(beanFactory);
        try {
            // 子類擴展注冊BeanDefinition
            postProcessBeanFactory(beanFactory);
            // BeanFactoryPostProcessor 用於對 BeanFactory 實例進行后置處理,重點包含ConfigurationClassPostProcessor會解析@Configuration注解的類進行注冊
            invokeBeanFactoryPostProcessors(beanFactory);
            // 注冊BeanPostProcessor,主要是AnnotationConfigUtils.registerAnnotationConfigProcessors注冊的BeanPostProcessor,如果是通過配置類創建的在上一步已經注冊了
            registerBeanPostProcessors(beanFactory);
            // 初始化國際化資源
            initMessageSource();
            // 初始化事件廣播器
            initApplicationEventMulticaster();
            // 子類實現,springboot中是EmbeddedWebApplicationContext創建web容器(Tomcat,jetty等)
            onRefresh();
            //將容器中解析出的ApplicationListener注冊到廣播器
            registerListeners();
            // 實例化所有非延遲加載的單例
            finishBeanFactoryInitialization(beanFactory);
            //發布上下文刷新完畢事件,調用所有實現了 Lifecycle 的 start 方法,調用web服務器的start方法
            finishRefresh();
        }

  

圖二:invokeBeanFactoryPostProcessors內部的調用流程

圖三:ConfigurationClassPostProcessor解析注解加載BeanDefinition的流程

總結:
1,擴展性強:通過ApplicationContextInitializer,SpringApplicationRunListener,SmartApplicationListener(或者EventListener注解)等在應用的啟動過程調用自定義行為,例如Spring Cloud就是通過BootstrapApplicationListener訂閱ApplicationEnvironmentPreparedEvent在啟動過程中實現了外部配置文件的加載

2,靈活:通過Configuration,Import等靈活的實現類注入簡化了配置,配合ConfigurationProperties極大的簡化了系統的初始化配置

參考:
http://zhaox.github.io/java/2016/03/22/spring-boot-start-flow

http://fangjian0423.github.io/2017/05/10/springboot-context-refresh/

http://www.zhenchao.org/2017/06/03/spring-src-application-context/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM