天天看點

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

作者:讀書人王元存

01 導引

大家好,我是王元存,今天我們繼續接着上一篇《搞清spring源碼的脈絡,你就知道從哪裡開始下手了》繼續深挖spring源碼,如果沒有看過上一篇建議翻一下公衆号在正經搞技術目錄下面。

好了廢話不多說,直接進入主題。

02 從一個測試類開始

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?
深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

我們從這個測試類debug進入我們今天非常重要的一個類ClassPathXmlApplicationContext的構造器:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

這個構造器裡面super(parent)這段代碼我們就不看了,主要就是一些調用父類的構造方法,對一些對象進行建立操作【這些我都在源碼上标了注釋了,如果有需要的可以私信我要github或者碼雲位址】。

我們來看看setConfigLocations(configLocations)這段代碼,這段代碼debug進入如下:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

通過注釋我們就可以大緻看出來setConfigLocations這個方法主要是設定應用程式的上下文的配置路徑.這個方法裡面有幾個地方需要注意的,我們直接進入resolvPath(locations[i]).trim()這個方法;

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

這個方法有兩個作用的地方,一個是getEnvironment()用于傳回一個環境配置(沒想好有其他更好的表達比環境配置更好說明)。

另外一個是resolveRequiredPlaceholders(path)看名稱我們就知道他是處理占位符的(例如:${...})。是以在我們看spring源碼時有些方法我們大可以見名知意。

我們主要講一下getEnvironment()這個方法,因為這個方法幹的事在後面會用到,是以大家要記住這個方法。

這個方法debug進去如下:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

因為剛進來是以這個environment肯定是沒有值的,我們進入了if裡面,點開createEnviroment()方法如下:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

這個地方有一個比較有意思的地方就是這個地方的内容是在父類構造器初始化的,但是實際執行其實是調用了子類的方法。這句話看着比較拗口,我們點進去StandardEnvironment()這個方法你就清楚了,debug進去如下圖:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

點進去之後你會發現這個類沒有做啥操作,這個地方涉及到了java的一個基本功:子類在初始化時首先會隐式的調用父類的無參構造器。

是以我們得去這個類的父類(AbstractEnvironment)的無參構造方法看看:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?
深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

這個customizePropertySources的實作正好在我們一開始進來的子類(StandardEnvironment)中進行了實作:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

這是不是感覺很繞,有點被套娃的感覺,這也是spring讓人頭疼的地方,針對上面的這個邏輯我畫了一下思維導圖如下:

深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

好了今天就分享到這裡,下一章我們繼續接着往下撸,下一章我們會撸

refresh()這個方法,這個方法是重點中的重點,大家一定要把搞明白。

關注我,一起讀書,一起提升認知!

原文連結:深入了解Spring源碼細節(1) -getEnvironment是怎麼擷取到值的?

公衆号:讀書人王元存