【SpringBoot】SmartLifecycle 的执行过程以及执行顺序

news/2024/9/22 16:35:48/文章来源:https://www.cnblogs.com/kukuxjx/p/18383873

1  前言

之前看过 SpringBoot 启动后,Tomcat监听端口也就是正式接收请求的开启时机以及启动时向注册中心注册服务的时机,都是在刷新上下文的 finishRefresh() 阶段通过执行生命周期的 Bean 来得到执行的。

当有多个 Bean 的话他们的执行顺序有没有什么说法呢,出于这个思考,我们本节就简单看一下。

2  源码分析

我们就从 finishRefresh 看起:

protected void finishRefresh() {// 清理资源缓存 Clear context-level resource caches (such as ASM metadata from scanning).
    clearResourceCaches();// 初始化LifecycleProcessor 生命周期处理器用于在启动或结束的时候处理Bean Initialize lifecycle processor for this context.
    initLifecycleProcessor();// 执行我们的生命周期  也是我们本节看的
    getLifecycleProcessor().onRefresh();// 发布ContextRefreshedEvent Publish the final event.publishEvent(new ContextRefreshedEvent(this));// Participate in LiveBeansView MBean, if active.// 如果配置了"spring.liveBeansView.mbeanDomain"的系统属性,指定了MBeanServer,// 那么会将ApplicationContext注册到MBeanServer中,// 可以通过MBeanServer,对spring容器中的bean,进行实时的查看和管理if (!NativeDetector.inNativeImage()) {LiveBeansView.registerApplicationContext(this);}
}

首先有一个初始化生命周期的处理器 initLifecycleProcessor 方法,这个主要是判断你有没有自己的 lifecycleProcessor 的Bean,没有的话就创建默认的 DefaultLifecycleProcessor。

protected void initLifecycleProcessor() {ConfigurableListableBeanFactory beanFactory = getBeanFactory();if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {this.lifecycleProcessor =beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);if (logger.isTraceEnabled()) {logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");}}else {DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();defaultProcessor.setBeanFactory(beanFactory);this.lifecycleProcessor = defaultProcessor;beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);if (logger.isTraceEnabled()) {logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");}}
}

然后执行到 getLifecycleProcessor().onRefresh(),我们进入到 DefaultLifecycleProcessor 的 onRefresh:

@Override
public void onRefresh() {startBeans(true);this.running = true;
}

接着看看内部的 startBeans 方法:

private void startBeans(boolean autoStartupOnly) {// 获取所有的 Lifecycle BeanMap<String, Lifecycle> lifecycleBeans = getLifecycleBeans();// 存放最后要执行的Bean key是 phase值Map<Integer, LifecycleGroup> phases = new TreeMap<>();lifecycleBeans.forEach((beanName, bean) -> {// 如果是 SmartLifecycle 并且开启了autoStartupOnly 或者是 autoStartupOnly 为 trueif (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {// 获取 Bean 的 phase 值 默认的 SmartLifecycle 的默认 phase值是 Integer.MAXint phase = getPhase(bean);// 其实就是根据 phase 分组放置
            phases.computeIfAbsent(phase,p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)).add(beanName, bean);}});if (!phases.isEmpty()) {List<Integer> keys = new ArrayList<>(phases.keySet());// 先根据 phase 升序排序
        Collections.sort(keys);// 每组执行 其实组内还会在排序一次 感觉没必要因为这个组内的 phase 值都一样的for (Integer key : keys) {phases.get(key).start();}}
}

可以看到决定顺序的就是 phase 值(越小越先执行),phase 值又是由 getPhase 方法得出的:

protected int getPhase(Lifecycle bean) {return (bean instanceof Phased ? ((Phased) bean).getPhase() : 0);
}
// SmartLifecycle 继承了 Phased 并提供了默认方法:
// int DEFAULT_PHASE = Integer.MAX_VALUE;
default boolean isAutoStartup() {return true;
}
default int getPhase() {return DEFAULT_PHASE;
}

所以当你的 SmartLifecycle 要先执行的话,就重写 getPhase 并把返回值设置的比 Integer.MAX_VALUE 小即可

简单画个图捋一下:

那我们最后再简单看下 SpringBoot 默认的情况下都有哪些 SmartLifecycle:

另外其实我写这篇之前我其实真正想去写的是服务启动时的注册时机以及 Tomcat 监听端口打开这两个时机的顺序,因为你比如我服务注册上了,可是我还没打开监听端口,那是不是就会导致别的服务调用异常么?是不是。这跟 Eureka 的机制有关,但是 Eureka 源码没怎么看过,所以我也说不好结论,我百科了一下, 服务注册的时候,会有心跳检测,你比如你注册是不是会看你这服务活没活着,活着的话才会变成 UP 可用状态,没活就不会变 UP,服务发现本身默认也有心跳检测以及服务的续约,所以这俩的顺序就变的不那么重要了,是不是。

3  小结

好啦,执行顺序主要是通过 SmartLifecycle 的 getPhase 值决定的,越小越优先执行,本节就看到这里,有理解不对的地方欢迎指正哈。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/788336.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

读软件开发安全之道:概念、设计与实施11安全地编程

安全地编程1. 安全地编程 1.1. 在一个完整的软件设计过程中,我们要在创建和审查时就将安全性放在心中,但这只是产品开发过程的开始,接下来是实现、测试、部署、运行、监控、维护,并最终在生命周期结束时将其淘汰 1.2. 开发人员不仅必须忠实地实现一个优良设计中明确的安全规…

使用RMBG-1.4进行抠图(背景移除)

使用RMBG-1.4进行抠图(背景移除) 说明:首次发表日期:2024-08-28 RMBG-1.4 Hugging Face 地址: https://huggingface.co/briaai/RMBG-1.4准备工作 创建环境并安装依赖:: # 如果`~/.local/lib/python3.10/site-packages`里面存在python模块,需要禁用。 ## 可以直接删除该…

maven远程仓库配置及含义解释

0 下载依赖的过程1 默认情况下maven会去中央仓库central找依赖或插件无需额外配置2 配置多个repository仓库时会先查找central仓库再依此查找多个repository仓库需要配置<profile><id>myprofile1</id><!--依赖仓库配置--><repositories><!--配…

迁移Swift项目到OC项目

文件迁移我直接把GuitarTunerApp文件夹迁移过去了 直接运行,提示 2个问题: 2.我们在我们先解决第2个,选择swift的版本: 选择项目文件,然后选择你的目标(Target)。 点击 "Build Settings" 选项卡。 确保 Swift Compiler - Language 下的 Swift Version 设置正确,…

Spring Boot+Dubbo

介绍Dubbo是阿里巴巴公司开源的一个高性能、轻量级的 Java RPC 框架。Zookeeper是一个开源的分布式的,为分布式应用提供协调服务的 Apache 项目。这里是需要使用到Zookeeper的,可以理解为Nacos和OpenFeign,需要把不同的服务注册到Zookeeper然后不同服务之间需要相互调用,则…

3.外设GPIO、中断

GPIO:通用输入输出端口GPIO特点:1.快速翻转,每次翻转最快只需要两个时钟周期(F1最高速度可以到50Mhz)2.每个IO口都可以做中断3.支持8种工作模式GPIO电气特性:STM32工作电压范围:2 V ≤ VDD ≤ 3.6 VGPIO识别电压范围:  COMS端口:-0.3V ≤ VIL ≤ 1.164V(0);1.833V …

桌面软件/exe程序软件自动化大宝剑--lackey之初识

C/S架构端下的软件在IT发展长河中,渐渐的在大多数从业者已经淡忘。现有的PC端上的软件 也是在极力的前浪推后浪,更新替代一些老派的语言追寻潮流。互联网的软件开发就是IOT,HTTPclient ,鲜有 exe的桌面软件;某也喜欢追新潮学互联网技 术,自动化就接触APP WEB API并使用网…

全网最适合入门的面向对象编程教程:40 Python常用复合数据类型-枚举和enum模块的使用

在 Python 中,枚举(Enumeration, Enum)是一种复合数据类型,用于表示一组相关但不同的常量值。枚举类型允许我们使用人类可读的名称代替代码中的魔法数字或字符串,Python 提供了 enum 模块来实现枚举类型。全网最适合入门的面向对象编程教程:40 Python 常用复合数据类型-…

rn node 版本问题

报错信息:Command PhaseScriptExecution failed with a nonzero exit codeFailed to construct transformer: Error: error:0308010C:digital envelope routines::unsupportedat new Hash (node:internal/crypto/hash:79:19)at Object.createHash (node:crypto:139:10)at sta…

替代BeyondCompare,四款免费文件代码对比工具分享

Beyond Compare是一套内容比较工具软件。除了可以作文件比较以外,还可以比对文件目录、FTP目录及压缩包案的内容等,但是由于要收费且比较贵,很多公司也在规避工作电脑使用非授权软件的风险,所以分享四款平替Beyond Compare的文件代码对比软件工具。1、WinMerge WinMerge是一…

替代BeyondCompare,免费四款文件代码对比工具分享

Beyond Compare是一套内容比较工具软件。除了可以作文件比较以外,还可以比对文件目录、FTP目录及压缩包案的内容等,但是由于要收费且比较贵,很多公司也在规避工作电脑使用非授权软件的风险,所以分享四款平替Beyond Compare的文件代码对比软件工具。1、WinMerge WinMerge是一…

markdown格式测试

Editor.md hhh换行TEST 1 2 3 a bq d HEAD TEST Smart Test ...--目录 (Table of Contents) [TOCM] 目录Editor.md换行TESTHEAD TESTSmart TestHeading 1Heading 2Heading 3Heading 4Heading 5Heading 6Heading 1 link Heading linkHeading 2 link Heading linkHeading 3 link …