当前位置: 首页 > news >正文

Spring-创建非懒加载的单例Bean源码

补充:关于扫描的逻辑

/*** Scan the class path for candidate components.* @param basePackage the package to check for annotated classes* @return a corresponding Set of autodetected bean definitions*/
public Set<BeanDefinition> findCandidateComponents(String basePackage) {if (this.componentsIndex != null && indexSupportsIncludeFilters()) {return addCandidateComponentsFromIndex(this.componentsIndex, basePackage);}else {return scanCandidateComponents(basePackage); // 大部分情况是这一种}
}

其中大部分情况是下面一种。上面这种的componentsIndex是为了提高扫描效率

当配置了spring.components文件(文件内容不为空),才会走上面的componentsIndex逻辑。

spring.components文件内容示例:(相当于告诉Spring要去扫描哪些Bean)

com.gax.service.UserService=org.springframework.stereotype.Component
#com.gax.service.OrderService=org.springframework.stereotype.Component

注意:以上配置的类上面仍然需要添加@Component,不添加会报Bean找不到的异常

实例化非懒加载的单例Bean源码:

// 遍历、合并、创建非懒加载单例Bean
@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) {// 获取合并后的BeanDefinitionRootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);// 非懒加载的单例Bean,注意这里是抽象的BeanDefinition,和抽象类区分开// <bean id='user' class='' abstract='true' scope='prototype'> 抽象的BeanDefinition// 抽象的BeanDefinition不能生成Bean,但是可以给其他Bean当父BeanDefinition// <bean id='userService' class='' parent='user'>if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {// 获取FactoryBean对象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) {// 创建真正的Bean对象(getObject()返回的对象)getBean(beanName);}}}else {// 创建Bean对象getBean(beanName);}}}// 所有的非懒加载单例Bean都创建完了后// 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();}}
}

注意:抽象的BeanDefinition和抽象类的区别。思考抽象的BeanDefinition有什么用?

getMergedLocalBeanDefinition合并BeanDefinition是什么意思?

这个方法非常重要,合并之后的BeanDefinition。合并属性等信息:自己定义了用自己的,自己没定义用父亲的

对于父子BeanDefinition,合并是生成一个新的BeanDefinition,原来的父子BeanDefinition不变,把合并后的属性添加给新的BeanDefinition。子BeanDefinition的属性覆盖父BeanDefinition的属性,这就是合并

合并后的BeanDefinition放在mergedBeanDefinitions里面,很重要

afterSingletonsInstantiated方法什么时候调用的?

所有的非懒加载单例Bean创建完之后,才会调用每个单例Bean的afterSingletonsInstantiated方法

isFactoryBean(beanName)方法,也很重要,很多地方有用到

@Override
public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {String beanName = transformedBeanName(name);Object beanInstance = getSingleton(beanName, false);if (beanInstance != null) {return (beanInstance instanceof FactoryBean);}// No singleton instance found -> check bean definition.if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {// No bean definition found in this factory -> delegate to parent.return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);}return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}/*** Check whether the given bean is defined as a {@link FactoryBean}.* @param beanName the name of the bean* @param mbd the corresponding bean definition*/
protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {Boolean result = mbd.isFactoryBean;if (result == null) {// 根据BeanDefinition推测Bean类型(获取BeanDefinition的beanClass属性)Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);// 判断是不是实现了FactoryBean接口result = (beanType != null && FactoryBean.class.isAssignableFrom(beanType));mbd.isFactoryBean = result;}return result;
}

相关文章:

Spring-创建非懒加载的单例Bean源码

补充&#xff1a;关于扫描的逻辑 /*** Scan the class path for candidate components.* param basePackage the package to check for annotated classes* return a corresponding Set of autodetected bean definitions*/ public Set<BeanDefinition> findCandidateCo…...

Techlink TL24G06 网络变压器 10G 基座单端口变压器

功能特征&#xff1a; 1、符合IEEE 802.3标准。 2、符合RoHS。 3、工作温度范围&#xff1a;0C至70C。 4、储存温度范围&#xff1a;-20C至125C。...

Python操作PDF:PDF文件合并与PDF页面重排

处理大量的 PDF 文档是非常麻烦的事情&#xff0c;频繁地打开关闭文件会严重影响工作效率。对于一大堆内容相关的 PDF 文件&#xff0c;我们在处理时可以将这些 PDF 文件合并起来&#xff0c;作为单一文件处理&#xff0c;从而提高处理效率。同时&#xff0c;我们也可以选取不同…...

删除链表的倒数第n个节点(C++解法)

题目 给你一个链表&#xff0c;删除链表的倒数第 n 个结点&#xff0c;并且返回链表的头结点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5], n 2 输出&#xff1a;[1,2,3,5]示例 2&#xff1a; 输入&#xff1a;head [1], n 1 输出&#xff1a;[]示例 3&#…...

Apache服务的搭建与配置(超详细版)

前言 Apache是一种常见的Web服务器软件&#xff0c;广泛用于Linux和其他UNIX操作系统上。它是自由软件&#xff0c;可以通过开放源代码的方式进行自由分发和修改。Apache提供了处理静态和动态内容的能力&#xff0c;而且还支持多种编程语言和脚本&#xff0c;如PHP、Python和P…...

设计模式大赏(一):桥接模式,组合模式

设计模式大赏&#xff08;一&#xff09;&#xff1a;桥接模式&#xff0c;组合模式 导言 本篇文章是设计模式大赏中的第一篇文章&#xff0c;这个系列的文章中我们主要将介绍一些常见的设计模式&#xff0c;主要是我在看Android源码中发现用到的一些设计模式。本篇文章将主要…...

数据通信——应用层(DHCP的原理与配置)

引言 假如我们的网络中有N台设备&#xff0c;它们都要设置IP地址&#xff0c;如果人工去一个个配置不仅不方便管理还很麻烦。因此我们用DHCP来自动分配地址。 一&#xff0c;系统的启动流程 不仅是计算机、很多网络设备的启动流程如下&#xff1a; 设备上电后&#xff0c;硬件…...

力扣151.反转字符串中的单词

原题链接&#xff1a;力扣151.反转字符串中的单词 全代码&#xff1a; 需要复刷 class Solution { public:void reverse(string& s, int start, int end){ //翻转&#xff0c;区间写法&#xff1a;左闭右闭 []for (int i start, j end; i < j; i, j--) {swap(s[i],…...

vim三种模式,文本操作(操作字符/光标,列出行号可视化块模式/多文件查看)

目录 vim--文本编辑器 功能 基本概念 命令/默认模式 插入模式 底行模式 文本操作 引入 移动光标位置 删除字符 -- x/dd 复制/粘贴字符 -- yw/yyp 替换文本 -- r / %s 底行模式 全局替换 -- /g 撤销操作 -- u / ctrlr 修改字符 -- cw 示例 跳行 -- ctrlg 底行…...

jquery控制easyui中combobox、textbox显示隐藏

//combobox下拉框 $("#下拉框id.combo").hide();//textbox输入框 $("#输入框id.textbox").hide(); 参考网址&#xff1a; https://blog.csdn.net/Coldmood/article/details/128279727...

Android拖放startDragAndDrop拖拽onDrawShadow静态添加xml布局View,Kotlin(4)

Android拖放startDragAndDrop拖拽onDrawShadow静态添加xml布局View&#xff0c;Kotlin&#xff08;4&#xff09; import android.content.ClipData import android.graphics.Canvas import android.graphics.Point import android.os.Bundle import android.util.Log import a…...

Servlet 初始化参数(web.xml和@WebServlet)

1、通过web.xml方式 <?xml version"1.0" encoding"UTF-8"?> <web-app xmlns"http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://xmlns.jcp.org/xm…...

shell_62.shell脚本生成一个标准的 SQL INSERT 语句

无论是将文件读入脚本&#xff0c;还是将数据从脚本输出到文件&#xff0c;都会用到文件重定向&#xff0c;这是一种很 常见的操作。本节中的示例脚本两种功能皆有。它会读取 CSV 格式的数据文件&#xff0c;输出 SQL INSERT 语句&#xff0c;并将数据插入数据库。 shell 脚本使…...

华为ICT——第五章语音处理理论与实践

目录 语言学&#xff1a; 主要应用场景&#xff1a; 语言学&#xff1a; 语言学&#xff1a; 语音学&#xff08;1&#xff09; 语音学&#xff08;2&#xff09; 语音处理介绍&#xff1a; 人类语音的来源&#xff1a; 语言数据&#xff1a; 语言信号预处理&#xff1a; …...

ardupilot开发 --- SLAM 篇

1. 视觉SLAM 1.1 深度相机的种类 结构光相机&#xff0c;如 Kinect1.0、RealSenseTOF相机&#xff0c;如 Kinect2.0双目相机&#xff0c;如 ZED详细参考&#xff1a;https://zhuanlan.zhihu.com/p/282776636 1.2 视觉SLAM算法 2D slam 与3D slam 应用场景有哪些不同&#x…...

Elasticsearch:在你的数据上训练大型语言模型 (LLM)

过去的一两年&#xff0c;大型语言模型&#xff08;LLM&#xff09;席卷了互联网。 最近 Google 推出的 PaLM 2 和 OpenAI 推出的 GPT 4激发了企业的想象力。 跨领域构思了许多潜在的用例。 多语言客户支持、代码生成、内容创建和高级聊天机器人都是一些例子。 这些用例要求 LL…...

拓展卡尔曼滤波EKF

How to fusion two Gauss Distribution N ( x , μ 0 , σ 0 ) N ( x , μ 1 , σ 1 ) N ( x , μ ′ , σ ′ ) \begin{equation} \begin{aligned} \mathcal{N}(x,\mu_0,\sigma_0) \mathcal{N}(x,\mu_1,\sigma_1) \mathcal{N}(x,\mu,\sigma) \\ \end{aligned} \end{equatio…...

第四章 应用SysML基本特性集的汽车示例 P2(断更)|系统建模语言SysML实用指南学习

仅供个人学习 使用试用版CSM很鸡肋&#xff0c;然后书中一些内容没有说明&#xff0c;自定义方面有点困难&#xff0c;第四章暂时停止 同时感觉画图的顺序也很随意&#xff1f;甚至需求图放在了后面&#xff0c;觉得很离谱。 准备跳过这一章节 汽车模型 续P1 序列图表示启…...

Vue入门——核心知识点

简介 Vue是一套用于构建用户界面的渐进式JS框架。 构建用户界面&#xff1a;就是将后端返回来的数据以不同的形式(例如&#xff1a;列表、按钮等)显示在界面上。渐进式&#xff1a;就是可以按需加载各种库。简单的应用只需要一个核心库即可&#xff0c;复杂的应用可以按照需求…...

使用opencv的tracking模块跟踪目标

OpenCV跟踪模块算法介绍 OpenCV的tracking模块是一个功能强大的跟踪算法库&#xff0c;包含多种用于跟踪对象的算法。它可以帮助你在连续的视频帧中定位一个物体&#xff0c;例如人脸、眼睛、车辆等。 在OpenCV的tracking模块中&#xff0c;一些主要的跟踪算法包括&#xff1…...

开源软件的商业化和测试挑战:测试从业者的专业视角

在当今的软件开发生态中&#xff0c;开源软件已从边缘走向核心&#xff0c;成为驱动技术创新的关键基础设施。然而&#xff0c;当开源项目从社区驱动的“为爱发电”模式&#xff0c;转向寻求可持续收入的商业化道路时&#xff0c;一系列复杂的挑战随之浮现。对于软件测试从业者…...

专业术语统计报告_分布式能源系统源储荷耦合特性及主动调控运行策略研究

专业术语统计报告_分布式能源系统源储荷耦合特性及主动调控运行策略研究 一、概要简析 【概要分析】 本文档《分布式能源系统源储荷耦合特性及主动调控运行策略研究》超用心地围绕研究主题展开了系统性探讨哦&#x1f61c;&#xff01;文档总字符数足足有250531&#xff0c;其中…...

PixEz-flutter全链路网络可靠性架构实战:从数据同步到动态优化

PixEz-flutter全链路网络可靠性架构实战&#xff1a;从数据同步到动态优化 【免费下载链接】pixez-flutter 一个支持免代理直连及查看动图的第三方Pixiv flutter客户端 项目地址: https://gitcode.com/gh_mirrors/pi/pixez-flutter 在移动应用开发中&#xff0c;网络请求…...

OpenClaw监控告警方案:Qwen3-14B驱动服务器异常检测

OpenClaw监控告警方案&#xff1a;Qwen3-14B驱动服务器异常检测 1. 为什么需要智能化的服务器监控 作为个人站长&#xff0c;我经历过太多次深夜被服务器宕机惊醒的噩梦。传统监控工具要么配置复杂&#xff08;比如PrometheusGrafana全家桶&#xff09;&#xff0c;要么告警方…...

如何用Listen1实现跨平台音乐播放?告别多平台切换的终极解决方案

如何用Listen1实现跨平台音乐播放&#xff1f;告别多平台切换的终极解决方案 【免费下载链接】listen1_chrome_extension one for all free music in china (chrome extension, also works for firefox) 项目地址: https://gitcode.com/gh_mirrors/li/listen1_chrome_extensi…...

Linux上的哔哩哔哩终极指南:从零开始掌握B站客户端完整教程

Linux上的哔哩哔哩终极指南&#xff1a;从零开始掌握B站客户端完整教程 【免费下载链接】bilibili-linux 基于哔哩哔哩官方客户端移植的Linux版本 支持漫游 项目地址: https://gitcode.com/gh_mirrors/bi/bilibili-linux 想要在Linux系统上流畅观看B站视频吗&#xff1f…...

使用VS Code开发SenseVoice-Small模型应用的完整指南

使用VS Code开发SenseVoice-Small模型应用的完整指南 1. 开发环境配置 1.1 基础环境准备 在开始开发SenseVoice-Small模型应用之前&#xff0c;需要先确保你的开发环境准备就绪。VS Code作为轻量级但功能强大的代码编辑器&#xff0c;非常适合这类AI模型的开发工作。 首先确…...

模糊PID vs 传统PID:在Simulink里调直流电机,哪个响应更快更稳?

模糊PID与传统PID的Simulink对决&#xff1a;直流电机控制性能深度评测 在工业自动化和机器人控制领域&#xff0c;直流电机的精准控制一直是工程师们关注的重点。面对日益复杂的控制需求&#xff0c;传统PID控制器虽然简单可靠&#xff0c;但在非线性、时变系统中表现往往不尽…...

LFM2.5-1.2B-Thinking-GGUF入门必看:llama.cpp+GGUF轻量模型部署全流程

LFM2.5-1.2B-Thinking-GGUF入门必看&#xff1a;llama.cppGGUF轻量模型部署全流程 1. 模型与平台介绍 LFM2.5-1.2B-Thinking-GGUF是Liquid AI推出的轻量级文本生成模型&#xff0c;专为低资源环境优化设计。该模型采用GGUF格式&#xff0c;结合llama.cpp运行时&#xff0c;能…...

你的 Android App 可能白白损失了 35% 的性能——R8 全模式配置详解

字节跳动的工程师优化启动速度时&#xff0c;可能花了数周分析 trace、改代码&#xff1b;Monzo 的团队却只改了一行配置&#xff0c;性能指标全线提升了 35%。这不是段子&#xff0c;是 Google 官方 blog 2026 年 3 月底发出来的案例。 问题来了&#xff1a;你的项目&#xff…...