【Spring底层原理】BeanFactory的实现
🐌个人主页: 🐌 叶落闲庭
💨我的专栏:💨
c语言
数据结构
javaEE
操作系统
Redis
石可破也,而不可夺坚;丹可磨也,而不可夺赤。
容器实现
- 一、BeanFactory实现的特点
- 1.1 BeanFactory实现
- 1.2 BeanFactory无法解析@Configuration和@Bean
一、BeanFactory实现的特点
1.1 BeanFactory实现
- BeanFactory是通过一个DefaultListableBeanFactory来实现的,首先要创建一个DefaultListableBeanFactory的实例对象,创建好后,就作为一个核心的spring容器,此时容器中还没有bean
- 这时需要创建bean的定义,主要是描述bean的特征,包括类型,scope(单例、多例),是否有初始化方法和销毁方法,根据这些描述信息就能知道bean有哪些特点,并根据这些描述信息将bean创建出来
- bean的定义通过
BeanDefinitionBuilder.genericBeanDefinition(Config.class)
创建,参数Config.class
表示将Config这个类交给BeanFactory管理 - 然后通过调用
getBeanDefinition()
将bean定义对象创建好,即
AbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition(com.dobbopro.TestBeanFactory.Config.class).setScope("singleton").getBeanDefinition();
- 接下来通过
beanFactory.registerBeanDefinition("config",beanDefinition);
将这个定义好的bean进行注册,注册好的bean的名字就是第一个参数config
- bean创建好后,可以进行验证,通过
beanFactory.getBeanDefinitionNames()
就可以得到bean的名字
代码实现:
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Author YJ* @Date 2023/10/1 20:36* Description:BeanFactory实现*/
public class TestBeanFactory {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();//定义beanDefinitionAbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition(com.dobbopro.TestBeanFactory.Config.class).setScope("singleton").getBeanDefinition();//注册beanDefinitionbeanFactory.registerBeanDefinition("config",beanDefinition);for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {System.out.println(beanDefinitionName); }}@Configurationstatic class Config{@Beanpublic Bean1 bean1() {return new Bean1();}@Beanpublic Bean2 bean2() {return new Bean2();}}static class Bean1{private static final Logger log = LoggerFactory.getLogger(Bean1.class);public Bean1() {log.debug("构造Bean1()");}@Autowiredprivate Bean2 bean2;public Bean2 getBean2() {return bean2;}}static class Bean2{private static final Logger log = LoggerFactory.getLogger(Bean2.class);public Bean2() {log.debug("构造Bean2()");}}
}
验证结果:
1.2 BeanFactory无法解析@Configuration和@Bean
- 经过上述代码可以看出,spring容器中只有一个config的bean,加了@Bean注解的Bean1和Bean2并没添加到容器中,说明BeanFactory无法解析@Configuration和@Bean
- @Configuration和@Bean的解析是由其他的类来实现的:
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
这个方法是给BeanFactory添加一些常用的后处理器,有了后处理器,就可以解析@Configuration和@Bean这些注解了,具备了BeanFactory的一些扩展功能- 调用这个方法后,就可以将带有注解@Bean对应的bean对象添加到BeanFactory(注意:此时运行代码还不会将带有@Bean注解的bean1和bean2补充到BeanFactory中,这时只是添加到了BeanFactory,还没有运行后处理器,相当于工厂中有bean这个东西,但是它们还没有工作)
public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();//定义beanDefinitionAbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition(com.dobbopro.TestBeanFactory.Config.class).setScope("singleton").getBeanDefinition();//注册beanDefinitionbeanFactory.registerBeanDefinition("config",beanDefinition);//给BeanFactory添加后处理器AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
- 要想让bean1和bean2运行起来,需要先通过
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class)
拿到Bean工厂中的所有后处理器,得到是一个Map集合,这个Map集合的key就是后处理器的名字,value就是它们的值,通过foeEach拿到每一个后处理器 - 最后进行打印
public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();//定义beanDefinitionAbstractBeanDefinition beanDefinition =BeanDefinitionBuilder.genericBeanDefinition(com.dobbopro.TestBeanFactory.Config.class).setScope("singleton").getBeanDefinition();//注册beanDefinitionbeanFactory.registerBeanDefinition("config",beanDefinition);//给BeanFactory添加后处理器AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().stream().forEach(beanFactoryPostProcessor -> {beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);});for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
相关文章:

【Spring底层原理】BeanFactory的实现
🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaEE 操作系统 Redis 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 容器实现 一、BeanFactory实现的特点1.1 Be…...

c++---I/o操作
5、文件操作 程序运行时产生的数据都属于临时数据,程序一旦运行结束都会被释放。 我们可以通过文件将数据持久化 C中对文件操作需要包含头文件 <fstream> 文件类型分为两种: 文本文件 - 文件以文本的ASCII码形式存储在计算机中二进制文件 - 文…...

UG\NX二次开发 用程序修改“用户默认设置”
文章作者:里海 来源网站:《里海NX二次开发3000例专栏》 简介 可以用程序修改“用户默认设置”吗?下面是用代码修改“用户默认设置->基本环境->用户界面->操作记录->操作记录语言”的例子。 效果 代码 #include <uf_defs.h> #include <NXOpen/NXExcept…...
什么是信号处理?如何处理信号?
C语言信号处理详解 第一部分:什么是信号? 信号是一种进程间通信的机制,用于通知进程发生了某种事件或异常情况。在C语言中,信号是一种软件中断,它可以被操作系统或其他进程发送给目标进程。每个信号都有一个唯一的数…...

谈谈 Redis 数据类型底层的数据结构?
谈谈 Redis 数据类型底层的数据结构? RedisObject 在 Redis 中,redisObject 是一个非常重要的数据结构,它用于保存字符串、列表、集合、哈希表和有序集合等类型的值。以下是关于 redisObject 结构体的定义: typedef struct redisObject {…...

九、GC收集日志
JVM由浅入深系列一、关于Java性能的误解二、Java性能概述三、了解JVM概述四、探索JVM架构五、垃圾收集基础六、HotSpot中的垃圾收集七、垃圾收集中级八、垃圾收集高级👋GC收集日志 ⚽️1. 认识GC收集日志 垃圾收集日志是一个重要的信息来源,对于与性能相关的一些悬而未决的…...

SimpleCG动画示例--汉诺塔动画演示
前言 SimpleCG的使用方法在前面已经介绍了许多,有兴趣的同学如果有去动手,制作一些简单动画应该没多大问题的。所以这次我们来演示一下简单动画。我们刚学习C语言的递归函数时,有一个经典例子相信很多同学都写过,那就是汉诺塔。那…...
反弹shell脚本(php-reverse-shell)
平时经常打靶机 这里贴一个 反弹shell的脚本 <?php // php-reverse-shell - A Reverse Shell implementation in PHP // Copyright (C) 2007 pentestmonkeypentestmonkey.net // // This tool may be used for legal purposes only. Users take full responsibility // f…...

XSS-labs
XSS常见的触发标签_xss标签_H3rmesk1t的博客-CSDN博客 该补习补习xss漏洞了 漏洞原理 网站存在 静态 和 动态 网站 xss 针对的网站 就是 动态网站 动态网站会根据 用户的环境 与 需求 反馈出 不同的响应静态页面 代码写死了 只会存在代码中有的内容 通过动态网站 用户体…...

C++简单实现AVL树
目录 一、AVL树的概念 二、AVL树的性质 三、AVL树节点的定义 四、AVL树的插入 4.1 parent的平衡因子为0 4.2 parent的平衡因子为1或-1 4.3 parent的平衡因子为2或-2 4.3.1 左单旋 4.3.2 右单旋 4.3.3 先左单旋再右单旋 4.3.4 先右单旋再左单旋 4.4 插入节点完整代码…...

UE4 Cesium 与ultra dynamic sky插件天气融合
晴天: 雨天: 雨天湿度: 小雪: 中雪: 找到该路径这个材质: 双击点开: 将Wet_Weather_Effects与Snow_Weather_Effects复制下来,包括参数节点 找到该路径这个材质,双击点开&…...

SpringCloud Gateway--Predicate/断言(详细介绍)下
😀前言 本篇博文是关于SpringCloud Gateway–Predicate/断言(详细介绍)下,希望你能够喜欢 🏠个人主页:晨犀主页 🧑个人简介:大家好,我是晨犀,希望我的文章可以…...

SOC芯片学习--GPIO简介
原创 硬件设计技术 硬件设计技术 2023-07-20 00:04 发表于广东 收录于合集#集成电路--IC7个 一、GPIO定义、分类: GPIO(英语:General-purpose input/output),通用型之输入输出的简称,其接脚可以供使用者由…...

skywalking源码本地编译运行经验总结
前言 最近工作原因在弄skywalking,为了进一步熟悉拉了代码下来准备debug,但是编译启动项目我就费了老大劲了,所以准备写这篇,帮兄弟们少踩点坑。 正确步骤 既然是用开源的东西,那么最好就是按照人家的方式使用&…...

K8s架构简述
以部署一个nginx服务说明kubernetes系统各个组件调用关系: 一旦kubernetes环境启动之后,master和node都会将自身的信息存储到etcd数据库中 一个nginx服务的安装请求会首先被发送到master节点的apiServer组件 apiServer组件会调用scheduler组件来决定到底…...
linkedlist和arraylist的区别
LinkedList和ArrayList都是常见的数据结构,用于存储和操作集合元素,如果需要频繁进行插入和删除操作,LinkedList可能更适合。如果需要快速随机访问和较小的内存占用,ArrayList可能更合适。 以下是它们之间存在一些关键的区别&…...

[尚硅谷React笔记]——第2章 React面向组件编程
目录: 基本理解和使用: 使用React开发者工具调试函数式组件复习类的基本知识类式组件组件三大核心属性1: state 复习类中方法this指向: 复习bind函数:解决changeWeather中this指向问题:一般写法:state.htm…...

嵌入式学习笔记(40)看门狗定时器
7.5.1什么是看门狗、有何用 (1)看门狗定时器和普通定时器并无本质区别。定时器可以设定一个时间,在这个时间完成之前定时器不断计时,时间到的时候定时器会复位CPU(重启系统)。 (2)系统正常工作的时候当然不希望被重启࿰…...

点击、拖拉拽,BI系统让业务掌握数据分析主动权
在今天的商业环境中,数据分析已经成为企业获取竞争优势的关键因素之一。然而,许多企业在面对复杂的数据分析工具时,却常常感到困扰。这些工具往往需要专业的技术人员操作,而且界面复杂,难以理解和使用。对业务人员来说…...
C++模拟题[第一周-T1] 扑克
[第一周-T1] 扑克 题目描述 斗地主是一种使用 A \tt A A 到 K \tt K K 加上大小王的共 54 54 54 张扑克牌来进行的游戏,其中大小王各一张,其它数码牌各四张。在斗地主中,牌的大小关系根据牌的数码表示如下: 3 < 4 < 5 …...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...