日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

springboot 的启动流程

發(fā)布時(shí)間:2025/3/19 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot 的启动流程 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、通過(guò)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外部類都是通過(guò)讀取配置文件來(lái)獲取和動(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類對(duì)象,ApplicationListener類對(duì)象,

SpringApplicationRunListener對(duì)象都是此流程。,則通過(guò)此函數(shù)SpringApplication.getSpringFactoriesInstances(ApplicationContextInitializer.class),獲取了配置文件的類名,并且實(shí)例化對(duì)象。 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開(kāi)始啟動(dòng)事件(EventPublishingRunListener#starting()),此接口最終會(huì)通知所有SPRING中注冊(cè)的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)建對(duì)應(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)用容器中所有注冊(cè)了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)行注冊(cè)到容器工廠,中間會(huì)調(diào)用beanFactoryPostProcesser,最終會(huì)對(duì)所有非延遲加載的單例BEAN進(jìn)行實(shí)例化和beanPostProcesser,填充屬性,字段注入等操作。

1.在refresh之前,容器內(nèi)只有系統(tǒng)BEAN,和當(dāng)前啟動(dòng)MAIN CLASS BEAN.

2.在refresh時(shí),會(huì)通過(guò)PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors調(diào)用到當(dāng)前容器中所有實(shí)現(xiàn)了BeanDefinitionRegistryPostProcessor的接口.

2.1. ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry為最重要的類,主要為解析和掃描當(dāng)前容器類中所有@configutaion,@Component,@bean,@import,@importResource,@ComposeScan等注解的類,并將新生產(chǎn)的類注冊(cè)到容器工廠中。

? ?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)獲取所有的工廠配置文件的配置類,然后注冊(cè)到容器工廠中。

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 對(duì)新的配置對(duì)象,會(huì)再次進(jìn)行配置注解解析處理,如果配置對(duì)象中還有@import,@composeScan,@bean等操作,則會(huì)再次處理注解,把子對(duì)象也注冊(cè)到容器工廠中。

3.把beanDefinner對(duì)象全部掃描注冊(cè)到容器工廠后,就會(huì)調(diào)用finishBeanFactoryInitialization創(chuàng)建非延遲加載的單例對(duì)象,注入屬性,調(diào)用BEAN的INITLIZE等消息。

總結(jié)

以上是生活随笔為你收集整理的springboot 的启动流程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。