基礎准備
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/
