springboot 的启动流程
一、通過SpringFactoriesLoader獲取系統(tǒng)中所有的SpringApplicationRunListener(備注:目前系統(tǒng)中只有這一個(gè)EventPublishingRunListener)。
private SpringApplicationRunListeners getRunListeners(String[] args) {Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };return new SpringApplicationRunListeners(logger,getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));}1.所有的SPRINGBOOT外部類都是通過讀取配置文件來獲取和動(dòng)態(tài)實(shí)例化的。
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories"; private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {MultiValueMap<String, String> result = cache.get(classLoader);if (result != null) {return result;}try {Enumeration<URL> urls = (classLoader != null ?classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));result = new LinkedMultiValueMap<>();while (urls.hasMoreElements()) {URL url = urls.nextElement();UrlResource resource = new UrlResource(url);Properties properties = PropertiesLoaderUtils.loadProperties(resource);for (Map.Entry<?, ?> entry : properties.entrySet()) {String factoryTypeName = ((String) entry.getKey()).trim();for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {result.add(factoryTypeName, factoryImplementationName.trim());}}}cache.put(classLoader, result);return result;}catch (IOException ex) {throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);}}2.如獲取系統(tǒng)中所有的ApplicationContextInitializer類對象,ApplicationListener類對象,
SpringApplicationRunListener對象都是此流程。,則通過此函數(shù)SpringApplication.getSpringFactoriesInstances(ApplicationContextInitializer.class),獲取了配置文件的類名,并且實(shí)例化對象。 private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicatesSet<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}二、發(fā)布SprintBoot開始啟動(dòng)事件(EventPublishingRunListener#starting()),此接口最終會(huì)通知所有SPRING中注冊的ApplicationListener,即是發(fā)布廣播事件。
SimpleApplicationEventMulticaster@Overridepublic void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));Executor executor = getTaskExecutor();for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {if (executor != null) {executor.execute(() -> invokeListener(listener, event));}else {invokeListener(listener, event);}}}三、創(chuàng)建對應(yīng)的ApplicationContext:Web類型,Reactive類型,普通的類型(非Web)
context = createApplicationContext();最終在WEB環(huán)境中是創(chuàng)建org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext
四、prepareContext,預(yù)處理上下文,
?1.首先會(huì)調(diào)用容器中所有注冊了ApplicationContextInitializer的接口,進(jìn)行初始化動(dòng)作通知。
SpringApplication類 protected void applyInitializers(ConfigurableApplicationContext context) {for (ApplicationContextInitializer initializer : getInitializers()) {Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(initializer.getClass(),ApplicationContextInitializer.class);Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");initializer.initialize(context);}}2.發(fā)布contextPrepared事件,listeners.contextPrepared(context),最終是廣播ApplicationContextInitializedEvent事件。
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(this.application, this.args, context));五、refreshContext,進(jìn)行容器工廠上下文刷新功能。這時(shí)會(huì)掃描各類注解,包掃描,進(jìn)行注冊到容器工廠,中間會(huì)調(diào)用beanFactoryPostProcesser,最終會(huì)對所有非延遲加載的單例BEAN進(jìn)行實(shí)例化和beanPostProcesser,填充屬性,字段注入等操作。
1.在refresh之前,容器內(nèi)只有系統(tǒng)BEAN,和當(dāng)前啟動(dòng)MAIN CLASS BEAN.
2.在refresh時(shí),會(huì)通過PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors調(diào)用到當(dāng)前容器中所有實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的接口.
2.1. ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry為最重要的類,主要為解析和掃描當(dāng)前容器類中所有@configutaion,@Component,@bean,@import,@importResource,@ComposeScan等注解的類,并將新生產(chǎn)的類注冊到容器工廠中。? ?2.2. 由于在MAIN類加入了@ComponentScan(basePackages = {"com.tpw.newday"}),所以此時(shí)會(huì)解析此注解,掃描根目錄包下所有的符合條件的類文件。并注入到容器工廠中。
2.3.@SpringBootApplication注解中包含@EnableAutoConfiguration,@EnableAutoConfiguration中又包含@Import(AutoConfigurationImportSelector.class),這個(gè)類是實(shí)現(xiàn)DeferredImportSelector,是一個(gè)延遲加載導(dǎo)入選擇類。
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @SpringBootConfiguration @EnableAutoConfiguration @ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) }) public @interface SpringBootApplication { @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited @AutoConfigurationPackage @Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration { public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {2.4 這個(gè)類會(huì)動(dòng)態(tài)獲取所有的工廠配置文件的配置類,然后注冊到容器工廠中。
AutoConfigurationImportSelector.AutoConfigurationGroup.process函數(shù)。 AutoConfigurationGroup@Overridepublic void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,() -> String.format("Only %s implementations are supported, got %s",AutoConfigurationImportSelector.class.getSimpleName(),deferredImportSelector.getClass().getName()));AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector).getAutoConfigurationEntry(annotationMetadata);this.autoConfigurationEntries.add(autoConfigurationEntry);for (String importClassName : autoConfigurationEntry.getConfigurations()) {this.entries.putIfAbsent(importClassName, annotationMetadata);}}2.5 對新的配置對象,會(huì)再次進(jìn)行配置注解解析處理,如果配置對象中還有@import,@composeScan,@bean等操作,則會(huì)再次處理注解,把子對象也注冊到容器工廠中。
3.把beanDefinner對象全部掃描注冊到容器工廠后,就會(huì)調(diào)用finishBeanFactoryInitialization創(chuàng)建非延遲加載的單例對象,注入屬性,調(diào)用BEAN的INITLIZE等消息。
總結(jié)
以上是生活随笔為你收集整理的springboot 的启动流程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: spring @order控制对象的顺序
- 下一篇: spring bean的生命周期和创建流
