成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringBoot運行源碼分析:Spring應(yīng)用上下文準(zhǔn)備

開發(fā) 前端
我們在上一節(jié)完成了應(yīng)用上下文的創(chuàng)建工作,SpringApplication 繼續(xù)通過 prepareContext方法來進行應(yīng)用上下文的準(zhǔn)備工作。首先,通過圖 4-4 來整體了解一下 prepareContext 的核心功能及流程。

Spring應(yīng)用上下文的準(zhǔn)備

我們在上一節(jié)完成了應(yīng)用上下文的創(chuàng)建工作,SpringApplication 繼續(xù)通過 prepareContext方法來進行應(yīng)用上下文的準(zhǔn)備工作。首先,通過圖 4-4 來整體了解一下 prepareContext 的核心功能及流程。

 

SpringBoot運行源碼分析:Spring應(yīng)用上下文準(zhǔn)備

配合流程圖,看一下 SpringApplication 中 prepareContext 方法源代碼及功能注解。

 

  1. private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment 
  2. environment, 
  3. SpringApplicationRunL 
  4. isteners 
  5. listeners , 
  6. Applicat ionArguments applicat ionArguments, Bann 
  7. er printedBanner) { 
  8. //沒置上下文的配置環(huán)境 
  9. context . setEnvironment (environment); 
  10. //應(yīng)用上下文后置處理 
  11. postProcessApplicationContext( context);//在 context 刷新之前,Appl icat ionContext Init 
  12. ial izer 初始化 context 
  13. applyInitializers(context); 
  14. //通知監(jiān)聽器 context 準(zhǔn)備完成,該方法以 上為上下文準(zhǔn)備階段,以下為上下文加載階段 
  15. listeners . contextPrepared(context);//打印日志,啟動 Profile 
  16. if (this . logStartupInfo)- 
  17. logStartupInfo(context . getParent() == nu1l); 
  18. logStartupProfileInfo( context); 
  19. //獲得 ConfigurableL istableBeanFactory 并炷冊單例對象 
  20. ConfigurableL istableBeanFactory beanFactory = context . getBeanFactory(); 
  21. beanFactory. registerSingleton("springApplicat ionArguments", applicationAr 
  22. guments); 
  23. if (printedBanner != null) { 
  24. //注冊打印日志對象 
  25. beanF actory. registerSingleton("springBootBanner", printedBanner); 
  26. if (beanFactory instanceof DefaultlistableBeanFactory) { 
  27. //沒置是否允許覆蓋炷冊 
  28. ((DefaultListableBeanFactory) beanFactory) 
  29. . setAllowBeanDefinitionOverriding(this . allowBeanDefinitionOverriding); 
  30. //獲取全部配置源,其中包含 primarySources 和 sources 
  31. Set<0bject> sources = getAllSources(); 
  32. Assert . notEmpty(sources, "Sources must not be empty"); 
  33. //將 sources 中的 Bean 加載到 context 中 
  34. load(context, sources . toArray(new 0bject[0])); 
  35. //遁知監(jiān)聽器 context 加載完成 
  36. listeners . contextLoaded(context); 

通過流程圖和具體代碼可以看出,在該方法內(nèi)完成了兩步操作:應(yīng)用上下文的準(zhǔn)備和加載。

下面我們針對具體的源代碼進行詳細(xì)講解。

應(yīng)用上下文準(zhǔn)備階段

在上下文準(zhǔn)備階段,主要有 3 步操作:對 context 設(shè) 置 environment、應(yīng)用上下文后置處理和 ApplicationContextlnitializer 初始化 context 操作。

首先是對 context 設(shè)置 environment,代碼和業(yè)務(wù)操作都很簡單。

 

  1. public void setEnvironment (ConfigurableEnvironment environment) { 
  2. //設(shè)置 context 的 environment 
  3. super. setEnvi ronment( environment); 
  4. //設(shè)置 context 的 reader 屬性的 conditionEvaluator 屬性 this.reade 
  5. er. settEnvironment(environment) ; 
  6. //設(shè)置 context 的 scanner 屬性的 environment 屬性 
  7. this. scanner. setEnvi ronment ( envi ronment); 

隨 后 , 便 是 進 行 Spring 應(yīng) 用 上 下 文 的 后置處理 , 這 一 步 是 通 過postProcessApplicationContext 方法來完成的。

 

  1. protected void postProcessApplicat ionContext (ConfigurableApplicat ionConEext 
  2. context){ 
  3. f (this. beanNameGenerator != null) { 
  4. // 如果 beanNameGenerator 為 null, 則將當(dāng)前的 beanNameGenerator 按照默認(rèn)名字進 
  5. 行注冊 
  6. context . getBeanFactory(). regi sterSingleton( 
  7. Annotat ionConfigUtils .CONF IGURATION BEAN NAME GENERATOR, 
  8. this . beanNameGenerator); 
  9. esourceLoader 為 null 時, 則根據(jù) context 的類型分別進行 Resourceloader 和 CL 
  10. assLoader 的設(shè)置 
  11. if (this .resourceLoader != null) { 
  12. F (context instanceof GenericApplicationContext) { 
  13. ((GenericApplicationContext) context) . setResourcel oader(this . resource 
  14. Loader); 
  15. if (context instanceof DefaultResourceLoader) { 
  16. ( (DefaultResourceLoader) context) 
  17. . setClassLoader(this.resourceLoader. getClassLoader()); 
  18. //如果為 true 則獲取并沒置轉(zhuǎn)換服務(wù) 
  19. f (this .addConversionService) { 
  20. context . getBeanFactory(). setConversionService( 
  21. ApplicationConversionService . getSharedInstance()); 

postProcessApplicationContext 方 法 主 要 完 成 上 下 文 的 后 置 操 作 , 默 認(rèn) 包 含beanNameGeneratorResourceL oader.ClassL oader 和 ConversionService 的設(shè)置。該方法可由子類覆蓋實現(xiàn),以添加更多的操作。

而在此階段,beanNameGenerator 和 resourceL oader 都為 null,因此只操作了最后-一步的設(shè)置轉(zhuǎn)換服務(wù)。

最后,在通知監(jiān)聽器 context 準(zhǔn)備完成之前,通過 applylnitializers 方法對上下文進行初始化。

所使用的 ApplicationContextInitializer 正是我們在 SpringApplication 初始化階段設(shè)置在itializers 變量中的值,只不過在通過 getlnitializers 方法獲取時進行了去重和排序。

 

  1. protected void applyInitializers(ConfigurableApplicat ionContext context) { 
  2. /獲取 Appl icat ionContextInitializer 集合并遍歷 
  3. for (ApplicationContextInitializer initializer : getInitializers()) { 
  4. //解析當(dāng)前 initial izer.實現(xiàn)的 Appl icat ionContextInitializer 的泛型參數(shù) 
  5. Class<?> requiredType = GenericTypeResolver . resolveTypeArgument( 
  6. initializer . getClass(), ApplicationContextInitializer.class); 
  7. 1 斷言判斷所需類似是否與 context 類型匹配 
  8. Assert. isInstanceOf(requiredType, context, "Unable to call initialize 
  9. r."); 
  10. // 初始化 context 
  11. initializer. initialize(context); 

完成以上操作之后,程序便調(diào)用 SpringApplicationRunListeners 的 contextPrepared 方法通知監(jiān)聽器,至此第一階段的準(zhǔn)備操作完成。

應(yīng)用上下文加載階段

應(yīng)用上下文加載階段包含以下步驟:打印日志和 Profile 的設(shè)置、設(shè)置是否允許覆蓋注冊、獲取全部配置源、將配置源加載入上下文、通知監(jiān)控器 contex 加載完成。

首先進入應(yīng)用上下文加載階段的操作為打印日志和 Profile 的設(shè)置,對此不展開講解。隨后,便是獲得 ConfigurableL istableBeanFactory 并注冊單例對象,注冊的單例對象包含:

ApplicationArguments 和 Banner。 當(dāng) BeanFactory 為 DefaultL istableBeanFactory 時,進入設(shè)置是否允許覆蓋注冊的處理邏輯。

此處需注意的是,當(dāng)進行了 ApplicationArguments 類單例對象的注冊之后,也就意味著我們在使用 Spring 應(yīng)用上下文的過程中可以通過依賴注入來使用該對象。

 

  1. @Resource 
  2. private ApplicationArguments applicat ionArguments; 

完成以.上操作后,便進入配置源信息的處理階段,這一步通過 getAllSources 方法來對配置源信息進行合并操作。

  1. public Set<Object> getAllSources() { 
  2. Set<0bject> allSources = new LinkedHashSet<>(); 
  3. if (!CollectionUtils.isEmpty(this . primarySources)) { 
  4. allSources.addAll(this.primarySources); 
  5. if (!CollectionUtils . isEmpty(this. sources)) { 
  6. allSources. addAll(this.sources); 

 

return Collections . unmodifiableSet(allSources); }以上操作邏輯很簡單,如果 Set 集合中不存在 primarySources 配置源或 sources 配置源,則將其添加入 Set 中,同時將 Set 設(shè)置為不可修改,并返回。

前面章節(jié)已經(jīng)提到,變量 primarySources 的值 來自 SpringApplication 的構(gòu)造參數(shù),變量sources 的值來自 setResources 方法。

當(dāng)獲得所有的配置源信息之后,通過 load 方法將配置源信息加載到上下文中,代碼如下。

 

  1. protected void load(ApplicationContext context, Object[] sources) { 
  2. /日志打印 
  3. BeanDefinitionLoader loader = createBeanDefinitionLoader( 
  4. getBeanDefinitionRegistry(context), sources); 
  5. f (this. beanNameGenerator != nu1l). 
  6. loader. setBeanNameGenerator(this . beanNameGenerator); 
  7. if (this.resourceLoader != nu1l) { 
  8. loader . setResourceLoader(this . resourceLoader); 
  9. if (this. environment != null) { 
  10. loader . setEnvironment (this . environment) ; 
  11. loader. load(); 

 

該方法主要通過 BeanDefinitionL oader 來完成配置資源的加載操作。我們進一步查看方法createBeanDefinitionL oader 的源代碼,會發(fā)現(xiàn)它最終調(diào)用了 BeanDefinitionL oader 的構(gòu)造方法,并進行初始化操作。

 

  1. BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) { 
  2. this. sources = sources; 
  3. this . annotatedReader = new AnnotatedBeanDefinitionReader(registry); 
  4. this . xmlReader = new XmlBeanDefinitionReader(registry); 
  5. if (isGroovyPresent()) 
  6. this. groovyReader = new GroovyBeanDefinitionReader(registry); 

通過 BeanDefinitionLoader 的構(gòu)造方法我們可以看到 BeanDefinitionLoader 支持基于AnnotatedBeanDefinitionReaderXmlBeanDefinitionReader、GroovyBeanDefinitionReader等 多種類型的加載操作。

在執(zhí)行完 BeanDefinitionL oader 的創(chuàng)建及基本屬性設(shè)置之后,調(diào)用其 load方法,該方法最終執(zhí)行以下代碼。

 

  1. private int load(0bject source) { 
  2. Assert. notNull(source, "Source must not be null"); 
  3. if (source instanceof Class<?>) { 
  4. return load((Class<?>) source); 
  5. }if (source instanceof Resource) 
  6. return load( (Resource) source); 
  7. if (source instanceof Package) { 
  8. return load( (Package) source); 
  9. if (source instanceof CharSequence) { 
  10. return load( (CharSequence) source); 
  11. throw new IllegalArgumentException("Invalid source type ”+ source. getC 
  12. lass());} 

 

從以上代碼可以看出,BeanDefinitionLoader 加載支持的范圍包括:

Class、Resource、 Package 和 CharSequence 四種。 前面我們已經(jīng)提到變量 sources的來源有 primarySources 配置源和 sources 配置源。變量 primarySources 在初始化時接收的類型為 Class,而變量 sources 通過 set(Set )方法接收的參數(shù)為 String 集合。

因此,在實際使用的過程中,Resource 和 Package 的判斷分支始終無法進入執(zhí)行階段。

完成以上操作后,接下來執(zhí)行 SpringApplicationRunListeners 的 contextL oaded 方法通知監(jiān)聽器上下文加載完成,至此整個 Spring 應(yīng)用上下文的準(zhǔn)備階段完成。

 

責(zé)任編輯:未麗燕 來源: 今日頭條
相關(guān)推薦

2017-05-11 14:00:02

Flask請求上下文應(yīng)用上下文

2024-02-21 19:56:48

??filterA并發(fā)計算

2022-10-31 15:34:30

python裝飾器內(nèi)存泄漏

2012-12-31 10:01:34

SELinuxSELinux安全

2022-09-14 13:13:51

JavaScript上下文

2022-06-29 14:15:01

Python計時器上下文管理器

2022-09-15 08:01:14

繼承基礎(chǔ)設(shè)施基礎(chǔ)服務(wù)

2017-12-17 17:01:23

限界上下文系統(tǒng)模型

2022-10-28 16:24:33

Context上下文鴻蒙

2024-09-30 14:10:00

2025-03-18 08:14:05

2023-07-11 10:02:23

2020-07-24 10:00:00

JavaScript執(zhí)行上下文前端

2021-07-26 07:47:36

Cpu上下文進程

2025-06-06 08:00:00

上下文管理器Python開發(fā)

2023-06-28 08:08:06

Flask上下文生命周期

2010-02-25 17:04:54

WCF實例上下文

2012-07-30 16:29:40

架構(gòu)架構(gòu)模式.NET

2022-04-24 15:37:26

LinuxCPU

2019-05-06 14:36:48

CPULinux寄存器
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: av免费网站在线观看 | 99re国产视频 | 成人午夜激情 | 黑人中文字幕一区二区三区 | 久草精品视频 | 欧美成视频| 亚洲美女在线一区 | 色偷偷噜噜噜亚洲男人 | 久久精品二区亚洲w码 | 一区日韩 | 亚洲精品久久久一区二区三区 | 国产成人a亚洲精品 | 狠狠热视频 | 久久电影一区 | 国产精品久久久久久久久久久久 | 欧产日产国产精品国产 | 久久人人爽人人爽人人片av免费 | 久久成人免费 | 黄色骚片| 999精品在线观看 | 欧美一区二区三区四区视频 | 小草久久久久久久久爱六 | 国产精品美女久久久 | 国产中文原创 | 国产精品美女久久久久久久网站 | 美国一级黄色片 | 日韩网站在线观看 | 一区二区三区视频在线观看 | 国产久| 一级美国黄色片 | 香蕉久久久久久 | 国产成人精品久久二区二区 | 毛片免费在线观看 | 成人av在线播放 | 日韩久久久久 | 久久久久久成人 | 日韩免费视频一区二区 | 亚洲 欧美 激情 另类 校园 | 国产精品成人一区二区三区吃奶 | 国产精品一区二区三区四区 | 国产在线一区二 |