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