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

SpringBoot bean加載順序怎樣查看(源碼解讀)

 更新時(shí)間:2023年09月04日 17:04:35   作者:amcomputer  
這篇文章主要介紹了SpringBoot bean加載順序怎樣查看(源碼解讀)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

背景

SpringBoot bean 加載順序如何查看,想看加載了哪些bean, 這些bean的加載順序是什么?

實(shí)際加載順序不受控制,但會(huì)有一些大的原則

1、按照字母順序加載(同一文件夾下按照字母數(shù)序;不同文件夾下,先按照文件夾命名的字母順序加載)

2、不同的bean聲明方式不同的加載時(shí)機(jī),順序總結(jié):@ComponentScan > @Import > @Bean

這里的ComponentScan指@ComponentScan及其子注解,Bean指的是@configuration + @bean   

同時(shí)需要注意的是

(1)Component及其子注解申明的bean是按照字母順序加載的

(2)@configuration + @bean是按照定義的順序依次加載的

(3)@import的順序,就是bean的加載順序

(4)在xml中,通過<bean id="">方式聲明的bean也是按照代碼的編寫順序依次加載的

(5)同一類中加載順序:Constructor >> @Autowired >> @PostConstruct >> @Bean

(6)同一類中加載順序:靜態(tài)變量 / 靜態(tài)代碼塊 >> 構(gòu)造代碼塊 >> 構(gòu)造方法(需要特別注意的是靜態(tài)代碼塊的執(zhí)行并不是優(yōu)先所有的bean加載,只是在同一個(gè)類中,靜態(tài)代碼塊優(yōu)先加載)

探索-源碼

入口:

public class TestApplication {
	public static void main(String[] args) {
		try {
			SpringApplication.run(TestApplication.class, args);
			LOGGER.info("SpringBoot Application Start!!!");
		} catch (Throwable e) {
			throw e;
		}
	}
}

其中 里面的run方法為:

public ConfigurableApplicationContext run(String... args) {
		long startTime = System.nanoTime();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
			**refreshContext**(context);
			afterRefresh(context, applicationArguments);
			Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);
			}
			listeners.started(context, timeTakenToStartup);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}
		try {
			Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);
			listeners.ready(context, timeTakenToReady);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

refreshContext(context);

private void refreshContext(ConfigurableApplicationContext context) {
		if (this.registerShutdownHook) {
			shutdownHook.registerApplicationContext(context);
		}
		**refresh**(context);
	}

AbstractApplicationContext#refresh

然后看倒數(shù)第二行:finishBeanFactoryInitialization(beanFactory);

org.springframework.context.support.AbstractApplicationContext#refresh

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
			// Prepare this context for refreshing.
			prepareRefresh();
			// Tell the subclass to refresh the internal bean factory.
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
			// Prepare the bean factory for use in this context.
			prepareBeanFactory(beanFactory);
				// Allows post-processing of the bean factory in context subclasses.
				postProcessBeanFactory(beanFactory);
				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// Invoke factory processors registered as beans in the context.
				invokeBeanFactoryPostProcessors(beanFactory);
				// Register bean processors that intercept bean creation.
				registerBeanPostProcessors(beanFactory);
				beanPostProcess.end();
				// Initialize message source for this context.
				initMessageSource();
				// Initialize event multicaster for this context.
				initApplicationEventMulticaster();
				// Initialize other special beans in specific context subclasses.
				onRefresh();
				// Check for listener beans and register them.
				registerListeners();
				// Instantiate all remaining (non-lazy-init) singletons.
				**finishBeanFactoryInitialization(beanFactory);**
				// Last step: publish corresponding event.
				finishRefresh();
			}

finishBeanFactoryInitialization(beanFactory)

然后看最后一行:beanFactory.preInstantiateSingletons();

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
		// Initialize conversion service for this context.
		if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
				beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
			beanFactory.setConversionService(
					beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
		}
		// Register a default embedded value resolver if no BeanFactoryPostProcessor
		// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:
		// at this point, primarily for resolution in annotation attribute values.
		if (!beanFactory.hasEmbeddedValueResolver()) {
			beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
		}
		// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
		String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
		for (String weaverAwareName : weaverAwareNames) {
			getBean(weaverAwareName);
		}
		// Stop using the temporary ClassLoader for type matching.
		beanFactory.setTempClassLoader(null);
		// Allow for caching all bean definition metadata, not expecting further changes.
		beanFactory.freezeConfiguration();
		// Instantiate all remaining (non-lazy-init) singletons.
		**beanFactory.preInstantiateSingletons();**
	}

beanFactory.preInstantiateSingletons()

在這里會(huì)對(duì) beanDefinitionNames 進(jìn)行遍歷,然后進(jìn)行 bean的實(shí)例化 和 組裝

因此這里的 beanDefinitionNames 這個(gè)列表決定了bean 的 注冊(cè)順序。

org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}
		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		**List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);**
		// Trigger initialization of all non-lazy singleton beans...
		for (String beanName : beanNames) {
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				if (isFactoryBean(beanName)) {
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							getBean(beanName);
						}
					}
				}
				else {
					getBean(beanName);
				}
			}
		}
		// Trigger post-initialization callback for all applicable beans...
		for (String beanName : beanNames) {
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
						.tag("beanName", beanName);
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					smartSingleton.afterSingletonsInstantiated();
				}
				smartInitialize.end();
			}
		}
	}

如果不能看,像圖中一樣,不能找到j(luò)ava.util.list這個(gè)類,可以使用下面這個(gè)方式,親測(cè)有效:

beanDefinitionNames.toArray()

后面的bean就不展示順序了。感興趣的讀者可以看自己springBoot項(xiàng)目的。

進(jìn)一步思考

beanDefinitionNames 列表如何來的呢?

答案是 ConfigurationClassPostProcessor 通過掃描 代碼+注解生成的,講bean 掃描解析成 beanDefinition, 同時(shí)把 bean定義,beanDefinition,注冊(cè)到 BeanDefinitionRegistry, 故有了beanDefinitionNames list。

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Hibernate處理多對(duì)多關(guān)系的實(shí)現(xiàn)示例

    Hibernate處理多對(duì)多關(guān)系的實(shí)現(xiàn)示例

    本文介紹了Hibernate中實(shí)現(xiàn)多對(duì)多關(guān)系的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-01-01
  • spring AOP的After增強(qiáng)實(shí)現(xiàn)方法實(shí)例分析

    spring AOP的After增強(qiáng)實(shí)現(xiàn)方法實(shí)例分析

    這篇文章主要介紹了spring AOP的After增強(qiáng)實(shí)現(xiàn)方法,結(jié)合實(shí)例形式分析了spring面向切面AOP的After增強(qiáng)實(shí)現(xiàn)步驟與相關(guān)操作技巧,需要的朋友可以參考下
    2020-01-01
  • springcloud中Feign超時(shí)提示Read timed out executing POST的問題及解決方法

    springcloud中Feign超時(shí)提示Read timed out executing

    Feign接口調(diào)用分兩層,Ribbon的調(diào)用和Hystrix調(diào)用,理論上設(shè)置Ribbon的時(shí)間即可,但是Ribbon的超時(shí)時(shí)間和Hystrix的超時(shí)時(shí)間需要結(jié)合起來,這篇文章給大家介紹springcloud之Feign超時(shí)提示Read timed out executing POST問題及解決方法,感興趣的朋友一起看看吧
    2024-01-01
  • Token安全存儲(chǔ)的幾種方式小結(jié)

    Token安全存儲(chǔ)的幾種方式小結(jié)

    在現(xiàn)代 Web 應(yīng)用中,身份認(rèn)證與授權(quán)是確保系統(tǒng)安全性的重要部分,Token被廣泛應(yīng)用,作為實(shí)現(xiàn)身份認(rèn)證的主要方式,然而,如何安全地存儲(chǔ)這些 Token,是每個(gè)開發(fā)者在構(gòu)建前端應(yīng)用時(shí)必須考慮的問題,本文將深入探討Token安全存儲(chǔ)的幾種方式,需要的朋友可以參考下
    2025-04-04
  • Window搭建部署RocketMQ步驟詳解

    Window搭建部署RocketMQ步驟詳解

    這篇文章主要介紹了Window搭建部署RocketMQ步驟詳解,RocketMq是一個(gè)由阿里巴巴開源的消息中間件,脫胎去阿里每部使用的MetaQ,在設(shè)計(jì)上借鑒了Kafka。,需要的朋友可以參考下
    2019-06-06
  • SpringBoot實(shí)現(xiàn)登錄校驗(yàn)(JWT令牌)

    SpringBoot實(shí)現(xiàn)登錄校驗(yàn)(JWT令牌)

    JWT全稱為JSON Web Token,是一種用于身份驗(yàn)證的開放標(biāo)準(zhǔn),本文主要介紹了SpringBoot實(shí)現(xiàn)登錄校驗(yàn)(JWT令牌),具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • SpringBoot定義過濾器、監(jiān)聽器、攔截器的方法

    SpringBoot定義過濾器、監(jiān)聽器、攔截器的方法

    本篇文章主要介紹了SpringBoot定義過濾器、監(jiān)聽器、攔截器的方法,具有一定的參考價(jià)值,有興趣的可以了解一下。
    2017-04-04
  • 深入解析SpringBoot中#{}和${}的使用

    深入解析SpringBoot中#{}和${}的使用

    本文主要介紹了深入解析SpringBoot中#{}和${}的使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2025-04-04
  • SpringBoot實(shí)現(xiàn)人臉識(shí)別等多種登錄方式

    SpringBoot實(shí)現(xiàn)人臉識(shí)別等多種登錄方式

    本文主要介紹了SpringBoot實(shí)現(xiàn)人臉識(shí)別等多種登錄方式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • JAVA值傳遞和引用傳遞方式

    JAVA值傳遞和引用傳遞方式

    文章總結(jié):在Java中,處理不可變集合時(shí),直接修改操作會(huì)拋出異常,正確的做法是使用可變集合類型,如ArrayList,或者通過流操作(stream().filter())來實(shí)現(xiàn)修改,理解Java方法參數(shù)的傳遞方式(值傳遞)是關(guān)鍵,這決定了如何正確地修改對(duì)象的狀態(tài)
    2024-11-11

最新評(píng)論

武汉市| 沁阳市| 聂荣县| 宣汉县| 鄂温| 湘西| 米易县| 城市| 山东省| 莲花县| 望谟县| 铜梁县| 六安市| 龙胜| 句容市| 绥滨县| 波密县| 海阳市| 铜鼓县| 道真| 贺州市| 兴隆县| 岳池县| 丰顺县| 砚山县| 巴林左旗| 得荣县| 洮南市| 华坪县| 伽师县| 望都县| 云南省| 修水县| 华容县| 江都市| 永济市| 连城县| 肇源县| 修水县| 罗山县| 临安市|