我的编程空间,编程开发者的网络收藏夹
学习永远不晚

SpringBoot bean如何查询加载顺序

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

SpringBoot bean如何查询加载顺序

这篇“SpringBoot bean如何查询加载顺序”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot bean如何查询加载顺序”文章吧。

背景

SpringBoot bean 加载顺序如何查看,想看加载了哪些bean, 这些bean的加载顺序是什么?

实际加载顺序不受控制,但会有一些大的原则:

按照字母顺序加载(同一文件夹下按照字母数序;不同文件夹下,先按照文件夹命名的字母顺序加载)
2、不同的bean声明方式不同的加载时机,顺序总结:@ComponentScan > @Import > @Bean
   这里的ComponentScan指@ComponentScan及其子注解,Bean指的是@configuration + @bean
   同时需要注意的是:
   (1)Component及其子注解申明的bean是按照字母顺序加载的
   (2)@configuration + @bean是按照定义的顺序依次加载的
   (3)@import的顺序,就是bean的加载顺序
   (4)在xml中,通过<bean id="">方式声明的bean也是按照代码的编写顺序依次加载的
   (5)同一类中加载顺序:Constructor >> @Autowired >> @PostConstruct >> @Bean
   (6)同一类中加载顺序:静态变量 / 静态代码块 >> 构造代码块 >> 构造方法(需要特别注意的是静态代码块的执行并不是优先所有的bean加载,只是在同一个类中,静态代码块优先加载)

探索-源码

入口:

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

然后看倒数第二行:finishBeanFactoryInitialization(beanFactory);

org.springframework.context.support.AbstractApplicationContext#refresh

@Overridepublic 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()

在这里会对 beanDefinitionNames 进行遍历,然后进行 bean的实例化 和 组装

因此这里的 beanDefinitionNames 这个列表决定了bean 的 注册顺序。

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

@Overridepublic 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();}}}

SpringBoot bean如何查询加载顺序

如果不能看,像图中一样,不能找到java.util.list这个类,可以使用下面这个方式,亲测有效:

beanDefinitionNames.toArray()

SpringBoot bean如何查询加载顺序

后面的bean就不展示顺序了。感兴趣的读者可以看自己springBoot项目的。

进一步思考

beanDefinitionNames 列表如何来的呢?

答案是 ConfigurationClassPostProcessor 通过扫描 代码+注解生成的,讲bean 扫描解析成 beanDefinition, 同时把 bean定义,beanDefinition,注册到 BeanDefinitionRegistry, 故有了beanDefinitionNames list。

以上就是关于“SpringBoot bean如何查询加载顺序”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

SpringBoot bean如何查询加载顺序

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

SpringBoot bean如何查询加载顺序

这篇“SpringBoot bean如何查询加载顺序”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“SpringBoot be
2023-07-05

springboot中怎么控制bean的加载顺序

这期内容当中小编将会给大家带来有关springboot中怎么控制bean的加载顺序,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。 1.为什么需要控制加载顺序springboot遵从约定大于配置的原则,极大
2023-06-16

spring或者springboot调整bean加载顺序的方式

这篇文章主要介绍了spring或者springboot调整bean加载顺序的方式,本文通过实例代码讲解三种调整类加载顺序的方式,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
2023-03-01

SpringBootbean查询加载顺序流程详解

当你在项目启动时需要提前做一个业务的初始化工作时,或者你正在开发某个中间件需要完成自动装配时。你会声明自己的Configuration类,但是可能你面对的是好几个有互相依赖的Bean
2023-03-12

SpringBoot中如何实现自己的bean优先加载

这篇文章主要介绍“SpringBoot中如何实现自己的bean优先加载”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“SpringBoot中如何实现自己的bean优先加载”文章能帮助大家解决问题。一、
2023-07-06

axuer如何看内联框架加载顺序

本篇内容介绍了“axuer如何看内联框架加载顺序”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!axuer看内联框架加载顺序1、打开Axure
2023-07-06

mysql查询如何添加序号

这篇文章主要讲解了“mysql查询如何添加序号”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“mysql查询如何添加序号”吧!mysql查询添加序号的方法:1、通
2023-02-15

在 MySQL 中,如何使用查询未检索到的列来指定排序顺序?

实际上,我们知道我们可以借助 ORDER BY 子句指定排序顺序。我们需要编写 ORDER BY 关键字,后跟要对表进行排序的列的名称。我们不必在查询中的 SELECT 关键字后面使用该列名称。示例mysql> Select Sr, Ite
2023-10-22

小程序开发如何添加节点的滚动位置查询请求

本文小编为大家详细介绍“小程序开发如何添加节点的滚动位置查询请求”,内容详细,步骤清晰,细节处理妥当,希望这篇“小程序开发如何添加节点的滚动位置查询请求”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。添加节点的滚动
2023-06-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录