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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

springboot源码分析之环境属性构造过程1

發布時間:2025/3/21 编程问答 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 springboot源码分析之环境属性构造过程1 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用springboot的目的就是在項目開發中,快速出東西,因此springboot對于配置文件的格式支持是非常豐富的,最常見的配置文件后綴有如下四種:properties、xml、yml、yaml,比如我們在springboot項目根目錄中配置了一個application.properties文件,則springboot項目啟動的時候就會自動將該文件的內容解析并設置到環境中,這樣后續需要使用該文件中配置的屬性的時候,只需要使用@value即可。同理application.xml、application.yml、application.yaml文件也會自動被加載并最終設置到環境中。

上面我們提到了環境,那么環境到底是個什么玩意呢?在這里提前說一下:我們這里關注的是源碼層面的事情。并非講解api如何使用。

大家首先思考一下,springboot項目如何啟動,這個到很簡單,無外乎引入springboot依賴包,設置項目啟動的main方法如下所示:

@EnableAutoConfiguration @ComponentScan(value = "cn.bainuoyoupin.web") public class Application {private static Logger logger = LoggerFactory.getLogger(Application.class);public static void main(String[] args) {long startTime = System.currentTimeMillis();SpringApplication.run(Application.class,args);logger.info("程序啟動花費時間為:" + (System.currentTimeMillis() - startTime) / 1000 + "秒");} }

上述的代碼非常的簡單,但是springboot做了非常多的事情,因為springboot代碼體系非常龐大,所以后續的文章是我們講解那些源碼就直接看那些源碼,把不需要了解的暫時放到一邊。因此在這里暫時先關注環境的創建源碼,我們快速定位到SpringApplication類中的public ConfigurableApplicationContext run(String... args)方法,該方法關于環境的準備代碼如下所示:

,... ApplicationArguments applicationArguments = new DefaultApplicationArguments( args); ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments); ...

prepareEnvironment方法從名字就可以看出來是準備環境(Environment),prepareEnvironment代碼如下:

private ConfigurableEnvironment prepareEnvironment( SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {//獲取或者創建環境ConfigurableEnvironment environment = getOrCreateEnvironment();//配置環境的信息configureEnvironment(environment, applicationArguments.getSourceArgs());//通知所有的觀察者,環境已經準備好了。listeners.environmentPrepared(environment);//將第一步創建的環境進行轉換if (isWebEnvironment(environment) && !this.webEnvironment) {environment = convertToStandardEnvironment(environment);}return environment; }

接下來,我們一步步的分析。

1.獲取或者創建環境。

getOrCreateEnvironment()方法如下所示:

private ConfigurableEnvironment getOrCreateEnvironment() {if (this.environment != null) {return this.environment;}if (this.webEnvironment) {return new StandardServletEnvironment();}return new StandardEnvironment(); }

上述代碼邏輯如下:

1.如果environment不為空則直接返回。

2.如果是web環境則直接實例化StandardServletEnvironment類。

3.如果不是web環境則直接實例化StandardEnvironment類。

注意:environment 為ConfigurableEnvironment類型。我們不妨看一下該類的層次圖如下所示:

????Environment接口是Spring對當前程序運行期間的環境的封裝(spring)。主要提供了兩大功能:profile和property(頂級接口PropertyResolver提供)。目前主要有StandardEnvironment、StandardServletEnvironment和MockEnvironment3種實現,分別代表普通程序、Web程序以及測試程序的環境。通過上述的getOrCreateEnvironment方法處理邏輯也是可以總結出來的。

2.環境的裝載

在上面的代碼中實例化了StandardServletEnvironment類(我自己的環境是web),實例化該類的時候肯定會實例化其父類AbstractEnvironment,AbstractEnvironment類的構造函數如下:

public AbstractEnvironment() {customizePropertySources(this.propertySources);}

需要注意一點,因為實例化的是StandardServletEnvironment類,jvm會自動觸發其父類中的構造函數,但是當前程序的this指針依然是StandardServletEnvironment。

this.propertySources屬性如下所示:

AbstractEnvironment.java

private final MutablePropertySources propertySources = new MutablePropertySources(this.logger); 我們繼續跟蹤customizePropertySources方法,如下所示: AbstractEnvironment.java protected void customizePropertySources(MutablePropertySources propertySources) {}

好吧,customizePropertySources方法竟然是個空的實現,但是注意一點,當前程序this是StandardServletEnvironment實例,我們不妨看一下StandardServletEnvironment類中是否重寫了該方法。果不其然,StandardServletEnvironment類重寫了customizePropertySources方法,詳細代碼如下所示:

StandardServletEnvironment.java

protected void customizePropertySources(MutablePropertySources propertySources) {//servletConfigInitParamspropertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));//servletContextInitParamspropertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));//jndiPropertiesif (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));}super.customizePropertySources(propertySources);}

上述的代碼中,propertySources為AbstractEnvironment.java中的propertySources字段,因為他是個引用類型,所以可以拿到指針即可修改其值。

雖然我們暫時還不知道propertySources要干啥,但是我們還是先看明白PropertySources到底要干啥。PropertySources類圖如下所示:

MutablePropertySources類內部持有一個propertySourceList集合,該集合的詳細定義如下:

private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<PropertySource<?>>();

注意:propertySourceList為List<PropertySource<?>>類型。

MutablePropertySources類提供了一系列對propertySourceList操作的方法:

addFirst:在propertySourceList 頭部添加元素。

addLast:在propertySourceList 尾部添加元素。

addAtIndex:在propertySourceList 指定的位置添加元素。

等等。

不管是哪個api均是對propertySourceList集合進行操作的,這一點我們了解就可以了。

2.1PropertySource類

PropertySource類是一個抽象類,代碼如下:

public abstract class PropertySource<T> {protected final String name;protected final T source; ...省略其他的方法 }

getSource()方法:,這個方法會返回得到屬性源的源頭。比如MapPropertySource的源頭就是一個Map,PropertiesPropertySource的源頭就是一個Properties。

name:我們可以理解為一個map中的key。

PropertySource類的子類結構如下:

RandomValuePropertySource:source是random。

ServletConfigPropertySource:source是ServletConfig。

ServletContextPropertySource:source是ServletContext。

JndiPropertySource:source是JndiLocatorDelegate。

StubPropertySource:source是Object。

MapPropertySource:source是Map<String, Object>。

了解了這些內容之后,我們再次看一下customizePropertySources方法的實現:

首先添加servletConfigInitParams,然后添加servletContextInitParams,其次判斷是否是jndi環境,如果是則添加jndiProperties,最后調用父類的customizePropertySources(propertySources)。

在跟進父類的customizePropertySources(propertySources)方法之前,我們總結一下MutablePropertySources類中propertySourceList已經存在的屬性為servletConfigInitParams、servletContextInitParams、jndiProperties(如果存在)。

StandardEnvironment類為StandardServletEnvironment類的父類,該類的customizePropertySources方法如下:

protected void customizePropertySources(MutablePropertySources propertySources) {propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));}

1、添加systemProperties

2、添加systemEnvironment。

上述的方法邏輯執行完畢之后,MutablePropertySources類中propertySourceList已經存在的屬性為servletConfigInitParams、servletContextInitParams、jndiProperties(如果存在)、systemProperties、systemEnvironment。

經過一系列的跟蹤getOrCreateEnvironment方法所做的事情已經分析完畢了。我們不妨繼往下看。

3.配置環境信息

configureEnvironment(environment, applicationArguments.getSourceArgs())方法詳細實現如下所示:

protected void configureEnvironment(ConfigurableEnvironment environment,String[] args) {configurePropertySources(environment, args);configureProfiles(environment, args);}

3.1配置屬性源

configurePropertySources(environment, args)方法的核心實現如下:

protected void configurePropertySources(ConfigurableEnvironment environment,String[] args) {MutablePropertySources sources = environment.getPropertySources();if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {sources.addLast(new MapPropertySource("defaultProperties", this.defaultProperties));}if (this.addCommandLineProperties && args.length > 0) {String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;if (sources.contains(name)) {PropertySource<?> source = sources.get(name);CompositePropertySource composite = new CompositePropertySource(name);composite.addPropertySource(new SimpleCommandLinePropertySource(name + "-" + args.hashCode(), args));composite.addPropertySource(source);sources.replace(name, composite);}else {sources.addFirst(new SimpleCommandLinePropertySource(args));}}}

1、如果defaultProperties不為空,則繼續添加defaultProperties。

2、如果addCommandLineProperties為true并且有命令參數,分兩步驟走:第一步存在commandLineArgs則繼續設置屬性;第二步commandLineArgs不存在則在頭部添加commandLineArgs。

上述的代碼執行完畢之后,MutablePropertySources類中propertySourceList已經存在的屬性為commandLineArgs、servletConfigInitParams、servletContextInitParams、jndiProperties(如果存在)、systemProperties、systemEnvironment、defaultProperties(如果存在)。

3.2配置Profiles

這個后續我們用到了再來講解。

本文我們暫時講解到這里,后續的文章中,我們繼續跟蹤屬性文件的加載規則以及加載過程。提前曝光一點:

commandLineArgs、servletConfigInitParams、servletContextInitParams、jndiProperties(如果存在)、systemProperties、systemEnvironment、defaultProperties(如果存在)中的屬性優先級從前到后依次降低。在最前面的使用優先級最高。

比如commandLineArgs中存在一個屬性a=1; systemProperties中存在一個屬性a=2,則我們程序使用的時候a=1,因為越靠前的優先級越高。通過上述的優先級我們可以發現一個規律,命令行的優先級最高、其次是程序中的、然后是系統的環境變量以及屬性、最后是默認的。

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的springboot源码分析之环境属性构造过程1的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 欧美成人精品欧美一级乱黄 | 精品一区电影国产 | 亚洲少妇30p | 国产aaa毛片 | 久久久精品人妻无码专区 | 三上悠亚在线一区二区 | 理论片在线观看理伦片 | 日韩成人av免费在线观看 | 少妇网站在线观看 | 69久人妻无码精品一区 | 6080成人| 欧美视频免费看欧美视频 | 精品一区二区在线观看视频 | 人人妻人人玩人人澡人人爽 | 精品一区二区在线视频 | 国产网站免费观看 | 天堂伊人网 | 中文亚洲av片不卡在线观看 | 国内久久精品视频 | 可以免费看毛片的网站 | 亚洲国产精品视频在线观看 | 在线观看深夜视频 | 九九热伊人 | 97精品一区 | 黑人玩弄人妻一区二 | 日韩伦乱 | 一本加勒比hezyo黑人 | 亚洲av电影一区 | 欧美一级免费看 | 国产欧美一区二区视频 | 精品人妻一区二区免费 | 亚洲热热 | 日本精品免费视频 | 日韩av一级片 | 第九色| 精品一区二区三区不卡 | 国精产品乱码一区一区三区四区 | 豆花视频在线播放 | 农村村妇真实偷人视频 | 国产麻豆乱码精品一区二区三区 | 欧美一级特黄视频 | 亚洲一区二区三区乱码 | 国产人妻精品一区二区三区不卡 | 亚洲欧美日韩激情 | 成人黄色大片在线观看 | 黄色成人在线播放 | 韩国美女啪啪 | fc2ppv色の美マンに中出し | 在线播放国产视频 | 国产乱仑 | 一级免费黄色片 | 欧美深性狂猛ⅹxxx深喉 | 成年人在线观看视频网站 | 日韩高清在线观看 | 久久在线视频精品 | 欧美精品久久久久久久 | 成人国产av一区二区三区 | 亚洲精品韩国 | 精品日韩| 金鱼妻日剧免费观看完整版全集 | 无码人妻久久一区二区三区不卡 | 久久九九久久九九 | 韩国伦理片在线观看 | 影音先锋美女 | 一区二区三区不卡在线 | 91老司机在线 | 欧美激情性做爰免费视频 | 欧美大白屁股 | av免费在线观看网站 | 都市激情久久 | 色播激情网 | 天天干人人干 | 亚洲熟妇无码一区二区三区 | 九九综合久久 | 色校园| 日本人妻换人妻毛片 | 国产超碰人人爽人人做人人爱 | 亚洲欧美在线免费 | 免费看日批 | 先锋av网| 美国黄色片网站 | 亚洲综合在线第一页 | 阿v天堂网 | 四虎色播 | www av| 久久免费少妇高潮久久精品99 | 美女黄页网站 | 国产精品国产三级国产专播品爱网 | 丁香六月久久 | 中文字幕乱码一区二区 | 久久影库| 中文亚洲av片在线观看 | av网站免费大全 | 三上悠亚 在线观看 | 成人中文字幕在线观看 | 欧美日韩一区在线播放 | 一区免费在线 | 国产精品一线二线 | 四虎视频在线 |