最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot深入淺出分析初始化器

 更新時間:2022年07月15日 09:55:39   作者:lhf2112  
這篇文章主要介紹了SpringBoot初始化器的分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

如有錯誤,望指正;

SpringBoot可以有三種方式定義初始化器,來為容器中增加自定義的對象,具體如下:

1、定義在spring.factories文件中,被SpringFactoriesLoader發(fā)現(xiàn)注冊;

在resources下建立META-INF文件夾,新建spring.factories文件,添加自定義的初始化器:
org.springframework.context.ApplicationContextInitializer=com.mooc.sb2.initializer.InitializerOne

2、SpringApplication初始化完成后手動添加;

SpringApplication springApplication = new SpringApplication(SbApplication.class);
springApplication.addInitializers(new InitializerTwo());
springApplication.run(args)

3、定義成環(huán)境變量,被DelegatingApplicationContextInitializer所發(fā)現(xiàn)注冊(優(yōu)先級最高)

application.properties中增加一項配置:
context.initializer.classes=com.mooc.sb2.initializer.ThirdInitializer

下面從代碼的角度,來看下這三種方式是如何加載的

對于第一種方法,可以跟進

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

繼續(xù)進入這個run方法:

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

還有一個run方法,我們繼續(xù)進入:

這個run方法代碼比較長,這里我們關(guān)注的是這部分:

exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);

我們進入這個getSpringFactoriesInstances方法,如下:

	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<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

我們先看這個loadFactoryNames方法,它調(diào)用了loadSpringFactories方法來獲取固定位置的配置信息:

loadSpringFactories的重點部分代碼如下:

        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;
		}

我們可以發(fā)現(xiàn)一個常量的定義:FACTORIES_RESOURCE_LOCATION,而它的值,就是

"META-INF/spring.factories"

這里就解釋了我們?yōu)槭裁匆约航ㄒ粋€配置文件在固定的目錄下,這樣springboot就成功讀取到了自定義的初始化器,加載到了cache中;下面我們回到SpringApplication.java中,繼續(xù)跟進getSpringFactoriesInstances方法。

在獲取到了初始化器的全限定名后,我們繼續(xù)看createSpringFactoriesInstances方法:

	private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
			ClassLoader classLoader, Object[] args, Set<String> names) {
		List<T> instances = new ArrayList<>(names.size());
		for (String name : names) {
			try {
				Class<?> instanceClass = ClassUtils.forName(name, classLoader);
				Assert.isAssignable(type, instanceClass);
				Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
				T instance = (T) BeanUtils.instantiateClass(constructor, args);
				instances.add(instance);
			}
			catch (Throwable ex) {
				throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
			}
		}
		return instances;
	}

主要使用了反射手段,來完成初始化器的實例化工作;在獲取了實例列表之AnnotationAwareOrderComparator.sort(instances);會將實例按照@Order的注解順序進行排序,在這里不進行詳述;

第二種初始化器是通過手動添加

第三種是通過DelegatingApplicationContextInitializer的initialize方法來調(diào)用的,首先,我們先看這個方法的代碼:

	@Override
	public void initialize(ConfigurableApplicationContext context) {
		ConfigurableEnvironment environment = context.getEnvironment();
		List<Class<?>> initializerClasses = getInitializerClasses(environment);
		if (!initializerClasses.isEmpty()) {
			applyInitializerClasses(context, initializerClasses);
		}
	}

其中,我們重點關(guān)注getInitializerClasses()方法

	private List<Class<?>> getInitializerClasses(ConfigurableEnvironment env) {
		String classNames = env.getProperty(PROPERTY_NAME);
		List<Class<?>> classes = new ArrayList<>();
		if (StringUtils.hasLength(classNames)) {
			for (String className : StringUtils.tokenizeToStringArray(classNames, ",")) {
				classes.add(getInitializerClass(className));
			}
		}
		return classes;
	}

這里的常量:

PROPERTY_NAME= "context.initializer.classes";

也就是我們配置文件的key,value值會被以‘,’為分界線進行分割,來獲得每個所需的系統(tǒng)初始化器的全限定名,并通過BeanUtis工具來進行初始化;

另:為什么DelegatingApplicationContextInitializer加載的初始化器是優(yōu)先于其他方式執(zhí)行呢?這是因為SpringApplication的run方法中的prepareContext方法會調(diào)用applyInitializers方法,applyInitializers方法的for循環(huán)會調(diào)用getInitializers方法來加載所有的初始化器,而DelegatingApplicationContextInitializer的Order=0,因此優(yōu)先級最高,會被最先加載;

到此這篇關(guān)于SpringBoot深入淺出分析初始化器的文章就介紹到這了,更多相關(guān)SpringBoot初始化器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解析本地方法映射Java層的數(shù)據(jù)類型

    解析本地方法映射Java層的數(shù)據(jù)類型

    這篇文章給大家介紹了本地方法映射Java層的數(shù)據(jù)類型,包括基礎(chǔ)類型映射,引用類型映射等等,對java層數(shù)據(jù)類型映射相關(guān)知識,感興趣的朋友跟隨腳本之家小編一起看看吧
    2018-03-03
  • eclipse下整合springboot和mybatis的方法步驟

    eclipse下整合springboot和mybatis的方法步驟

    這篇文章主要介紹了eclipse下整合springboot和mybatis的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • solr在java中的使用實例代碼

    solr在java中的使用實例代碼

    本篇文章主要介紹了solr在java中的使用實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • Scala異常處理的方法深入分析

    Scala異常處理的方法深入分析

    Scala是一種多范式的編程語言,支持面向?qū)ο蠛秃瘮?shù)式編程。Scala也支持異常處理,即在程序運行過程中發(fā)生意外或錯誤時,采取相應(yīng)的措施
    2023-04-04
  • Java CountDownLatch完成異步回調(diào)實例詳解

    Java CountDownLatch完成異步回調(diào)實例詳解

    這篇文章主要介紹了Java CountDownLatch完成異步回調(diào)實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • idea導(dǎo)入項目爆紅問題記錄以及解決

    idea導(dǎo)入項目爆紅問題記錄以及解決

    這篇文章主要介紹了idea導(dǎo)入項目爆紅問題記錄以及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • 一篇文章帶你了解初始Spring

    一篇文章帶你了解初始Spring

    這篇文章主要給大家介紹了一個簡單的Spring容器初始化流程的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-08-08
  • 聊聊java 過濾器、監(jiān)聽器、攔截器的區(qū)別(終結(jié)篇)

    聊聊java 過濾器、監(jiān)聽器、攔截器的區(qū)別(終結(jié)篇)

    這篇文章主要介紹了聊聊java 過濾器、監(jiān)聽器、攔截器的區(qū)別(終結(jié)篇),具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • SpringMvc微信支付回調(diào)示例代碼

    SpringMvc微信支付回調(diào)示例代碼

    微信一直是一個比較熱門的詞匯,今天這篇文章主要介紹的是SpringMvc微信支付回調(diào)的示例代碼,對大家開發(fā)微信支付具有一定的參考借鑒價值,下面來一起看看吧。
    2016-09-09
  • 圖解Java中插入排序算法的原理與實現(xiàn)

    圖解Java中插入排序算法的原理與實現(xiàn)

    插入排序的算法描述是一種簡單直觀的排序算法。它的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入。本文將通過圖片詳解插入排序的原理及實現(xiàn),需要的可以參考一下
    2022-08-08

最新評論

云浮市| 大方县| 鞍山市| 新乡市| 高要市| 文水县| 六安市| 西安市| 安庆市| 华宁县| 西乌珠穆沁旗| 略阳县| 济南市| 三都| 双鸭山市| 尼木县| 密云县| 依兰县| 昌邑市| 武宣县| 凤凰县| 章丘市| 宜丰县| 梅河口市| 泗水县| 保定市| 山西省| 阿克陶县| 潞城市| 武胜县| 连江县| 广平县| 毕节市| 尚志市| 昆明市| 海盐县| 门源| 孙吴县| 八宿县| 怀仁县| 宁德市|