精品欧美激情精品一区,亚洲自拍的二区三区,亚洲综合精品一区二区,国产伦精品一区二区三区视频免费


學AI,好工作 就找北大青鳥
關注小青 聽課做題,輕松學習
周一至周日
4000-9696-28

你還在用SpringBoot嗎?別人都已經去研究源碼了

來源:北大青鳥總部 2023年01月12日 11:05

摘要: SpringBoot是怎么做到的約定的配置?它配置在了哪里?來一起跟隨源碼探究下SpringBoot到底是如何做到"約定優于配置"的。

我們都知道SpringBoot自問世以來,一直有一個響亮的口號"約定優于配置",其實一種按約定編程的軟件設計范式,目的在于減少軟件開發人員在工作中的各種繁瑣的配置,我們都知道傳統的SSM框架的組合,會伴隨著大量的繁瑣的配置;稍有不慎,就可能各種bug,被人發現還以為我們技術很菜。而SpringBoot的出現不僅大大提高的開發人員的效率,還能避免由于"手抖"帶來的配置錯誤。


很多程序員都感慨SpringBoot的到來大大解放了生產力,但是也有聰明的程序猿會多思考一下下,SpringBoot是怎么做到的約定的配置?它配置在了哪里?又是怎么啟動的作用等等一系列的問號在跟女朋友花前月下的時候,依然會是不是冒出來。這嚴重影響了程序猿們的"幸"福生活,為了能廣大"程序猿"同胞過上幸福美滿的生活,今天咱么就來一起跟隨源碼探究下SpringBoot到底是如何做到"約定優于配置"的。

首先,我們先介紹下我們的演示的項目環境,我們先試用Spring Initializr來創建一個SpirngBoot工程。我們使用的版本是SpringBoot 2.1.5.RELEASE。



接下來就只在pom.xml文件中添加一個web工程的依賴,是為了觀察后面容器類型的源碼。

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

這樣我們的環境就準備好了。

我們跟著SpringBoot的源碼來探究它的啟動流程,首先,先找到這個應用程序的入口主方法,在上面打一個斷點



啟動之后,F5進入到run()方法

public static ConfigurableApplicationContext run(Class<?>[] primarySources,String[] args) {
return new SpringApplication(primarySources).run(args);
}

到這里會執行new SpringApplication(primarySources)創建spring應用對象,繼續F5往下跟會執行SpringApplication構造器

// SpringApplication構造器
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 資源加載器
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 1. 可能的web應用程序類型的類型。
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 2. 設置初始化應用context
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
// 3.設置初始化監聽
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 4. 推演主程序類
this.mainApplicationClass = deduceMainApplicationClass();
}

很多不為人知的事情都是發生在這個對象初始化的時候,這里我們都來一一解密

static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
// 這里是我們測試web容器
return WebApplicationType.SERVLET;
}


一、推斷web應用類型

這段代碼是來推斷我們的應用是哪種web應用程序

public enum WebApplicationType {

/**
* The application should not run as a web application and should not start an
* embedded web server.
*/
NONE, // 不是web應用

/**
* The application should run as a servlet-based web application and should start an
* embedded servlet web server.
*/
SERVLET, // servlet容器

/**
* The application should run as a reactive web application and should start an
* embedded reactive web server.
*/
REACTIVE; // 反應型web應用(webflux)

當然一開始我們加入了web的依賴,所以我們是servlet容器,


二、初始化應用上下文

在設置初始化應用context的時候 ,是先執行了`getSpringFactoriesInstances(ApplicationContextInitializer.class)方法,參數是ApplicationContextInitializer.class字節碼對象

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
// 加載ApplicationContextInitializer.class類型的類
// 這里傳入就是參數 ApplicationContextInitializer.clas
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 實例化加載到的類
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
// 返回
return instances;
}

public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}

我們先來看看他是如何加載到這些類

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// 先從緩存中拿
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
// 去資源路徑下加載
public static final String ACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
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 factoryClassName = ((String) entry.getKey()).trim();
for (String factoryName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
// 返回所有的加載的類
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +
FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}

這里有兩個加載配置類的地方其實都指向了META-INF/spring.factories,通過斷點我們可以看到應用程序是加載了以下幾個jar下的spring.factores文件。

雙擊Shift搜索spring.factories可以看到它存在于以下工程中



spring-boot-2.1.5.RELEASE.jar下的spring.factores(截圖未完整截?。?/p>



spring-boot-autoconfigure-2.1.5.RELEASE.jar下的spring.factores



spring-beans-5.1.7.RELEASE.jar下的spring.factores



從Map中根據org.springframework.context.ApplicationContextInitializer的類型拿到需要的類初始化類,斷點進入getOrDefault(factoryClassName, Collections.emptyList());方法



之后就是把加載到的需要初始化的類進行實例化添加到一個集合中等待備用

public void setInitializers(
Collection<? extends ApplicationContextInitializer<?>> initializers) {
this.initializers = new ArrayList<>();
this.initializers.addAll(initializers);
}


三、初始化監聽器類

最關鍵的的還是這句



當我們跟進去之后,會發現在初始化監聽類的時候和上面初始化應用上下文是一樣的代碼。唯一不同的是getSpringFactoriesInstances(ApplicationListener.class))傳進去的是·ApplicationListener.class所以這里就不再贅述。


四、推演主程序類

也就是這個最關鍵的代碼了

this.mainApplicationClass = deduceMainApplicationClass();




到這里就完成了SpringBoot啟動過程中初始化SpringApplication的過程。


小結

這篇文章主要是給大家說了下SpringBoot啟動過程中初始化SpringApplication的流程,大致可以分為四個步驟:

推演web應用的類型(如果沒有加web依賴類型NONE)

初始化ApplicationContextInitializer

初始化ApplicationListener

推演出主程序類

通過這樣四個步驟就完成了第一步SpringApplication的初始化過程。


標簽: springboot
熱門班型時間
人工智能就業班 即將爆滿
AI應用線上班 即將爆滿
UI設計全能班 即將爆滿
數據分析綜合班 即將爆滿
軟件開發全能班 爆滿開班
網絡安全運營班 爆滿開班
報名優惠
免費試聽
課程資料
官方微信
返回頂部
培訓課程 熱門話題 站內鏈接
精品欧美激情精品一区,亚洲自拍的二区三区,亚洲综合精品一区二区,国产伦精品一区二区三区视频免费
首页综合国产亚洲丝袜| 91在线视频观看| 97超碰人人看人人| 日本不卡一区二区三区视频| 欧美区一区二区三区| 国产欧美一区二区三区在线老狼 | 国产69精品一区二区亚洲孕妇 | 26uuu国产日韩综合| 一区二区高清在线| 国产精品香蕉一区二区三区| 精品国产免费人成电影在线观...| 中文字幕中文字幕一区三区| 精品福利视频一区二区三区| 亚洲一区二区三区四区五区黄 | 日韩电影免费观看在| 91精品国产手机| 亚洲免费资源在线播放| 国产精品亚洲成人| 精品国产一区二区三区麻豆免费观看完整版| 综合网五月天| 国产精品网站导航| 久久99久久久欧美国产| 韩日午夜在线资源一区二区| 欧美日韩综合色| 亚洲三级在线免费| 国产99久久久久| 亚洲成色www久久网站| 久久久亚洲精品石原莉奈| 肉肉av福利一精品导航| 成人在线视频网址| 欧美日韩在线一区二区| 亚洲人xxxx| 成人激情免费电影网址| 制服诱惑一区| 日韩一区在线播放| 成人午夜电影网站| 色素色在线综合| 国产精品国产三级国产有无不卡| 国产在线国偷精品产拍免费yy| 狼狼综合久久久久综合网| 日韩精品一区在线| 日本少妇一区二区| 久久国产欧美精品| 精品国产免费一区二区三区香蕉| 日韩精品91亚洲二区在线观看| 成人永久免费| 日韩午夜精品视频| 日韩av电影免费观看高清完整版 | 国产伦精品一区二区三区在线观看| 区一区二区三区中文字幕| 亚洲精品一区二区三区精华液 | 不卡视频一二三| 色88888久久久久久影院野外| 国产精品嫩草影院com| 国产成人av电影免费在线观看| 亚洲一区二区在线免费观看| 中文字幕精品三区| 国产+成+人+亚洲欧洲自线| 综合操久久久| 亚洲黄色片在线观看| 波多野结衣成人在线| 日韩免费性生活视频播放| 免费的成人av| 先锋在线资源一区二区三区| 国产精品久久久久久福利一牛影视 | 日本a级片久久久| 欧美高清在线视频| 成人久久18免费网站麻豆 | 亚洲第一导航| 亚洲免费在线视频一区 二区| 91美女精品福利| 欧美成人伊人久久综合网| 精品一区二区在线免费观看| 亚洲图片都市激情| 一区二区在线免费| 久久大香伊蕉在人线观看热2| 久久这里都是精品| 成人午夜av影视| 欧美一卡二卡三卡| 国产一区二区视频在线播放| 91极品美女在线| 日韩国产欧美在线播放| 视频一区二区在线| 亚洲主播在线播放| 欧美国产二区| 亚洲人成在线观看一区二区| 国产欧美日韩视频一区二区三区| 久久久久久影视| 97se狠狠狠综合亚洲狠狠| 日韩欧美国产一区在线观看| 国产一区二区日韩精品| 欧美亚洲精品一区| 奇米影视一区二区三区小说| 亚洲砖区区免费| 香蕉av福利精品导航| 色999五月色| 亚洲国产毛片aaaaa无费看| 日韩国产伦理| 亚洲一区二区av电影| 天堂精品一区二区三区| 亚洲一二三四在线| 亚洲国产精品毛片| 亚洲不卡av一区二区三区| 亚洲欧美日韩精品久久久| 亚洲超碰精品一区二区| 伊人久久av导航| 免费在线成人网| 欧美色爱综合网| 国产剧情一区在线| 欧美一区二区视频在线观看| 福利一区二区在线| 2019国产精品| av成人在线电影| 国产精品国产三级国产aⅴ入口 | 成人听书哪个软件好| 日韩精品一区二区在线观看| 波多野结衣欧美| 国产午夜精品久久| 激情视频在线观看一区二区三区| 亚洲人成精品久久久久| 日日噜噜噜噜夜夜爽亚洲精品| 午夜精品一区在线观看| 日本高清无吗v一区| 国内精品视频一区二区三区八戒 | 亚洲一区二区三区在线观看视频| 日韩av电影免费观看高清完整版在线观看| 色久综合一二码| 国产高清在线观看免费不卡| 日韩精品一区二区三区三区免费| 99精品一区二区三区| 国产精品美女久久久久久| 欧美日韩国产一二| 日韩成人免费看| 91.麻豆视频| 97精品国产97久久久久久久久久久久| 欧美激情在线一区二区| 欧美极品色图| 日本一不卡视频| 日韩亚洲欧美一区二区三区| 97久久精品午夜一区二区| 亚洲图片激情小说| 色综合久久88色综合天天6| 国产一区不卡视频| 久久精品人人做人人综合| 欧美激情视频一区二区三区| 视频一区国产视频| 欧美一区二区三区四区高清| 91丝袜美腿高跟国产极品老师| 最新日韩av在线| 色噜噜狠狠一区二区三区果冻| 国产精品一区二区免费不卡| 久久久99精品久久| 欧洲亚洲一区二区三区四区五区| 免费观看成人鲁鲁鲁鲁鲁视频| 日韩午夜在线播放| 精品午夜一区二区| 奇米影视一区二区三区小说| 日韩视频一区二区三区| 国产原创精品| 蜜桃久久久久久久| 精品国产乱码久久久久久久久| 久久国产一区二区| 蜜臀va亚洲va欧美va天堂| 精品国产91亚洲一区二区三区婷婷| 国产偷久久久精品专区| 亚洲成av人片www| 欧美电影免费观看高清完整版在线 | 国产精品夜夜嗨| 中文字幕一区在线观看视频| 在线观看欧美一区| 成人福利视频网站| 亚洲欧美日韩国产成人精品影院| 欧美做爰猛烈大尺度电影无法无天| av电影天堂一区二区在线 | 国产一区视频在线看| 国产精品久久网站| 欧美在线视频你懂得| 成人av播放| 免费精品视频在线| 欧美国产丝袜视频| 91黄色免费网站| 岛国一区二区三区高清视频| 五月婷婷激情综合| 久久蜜桃av一区二区天堂| 亚洲一区二区不卡视频| av欧美精品.com| 日韩高清一级片| 国产视频不卡一区| 在线免费视频一区二区| av一本久道久久波多野结衣| 日韩成人免费电影| 国产欧美一区二区在线| 在线一区二区三区四区五区| www日韩av| 精品在线观看免费| 亚洲免费在线视频一区 二区| 欧美一区二区三区系列电影| 日本一区视频在线播放| 成人av午夜影院| 青青草97国产精品免费观看|