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

03Spring底层架构核心概念解析

为了感谢罕哥对我工作的帮助,特此记录下学习过程,期待成为和罕哥一样优秀的人

时间:2024.7.13

内容:spring源码课程3学习记录

一、BeanDefinition

BeanDefinition表示Bean的定义,BeanDefinition中存在很多属性用来描述一个Bean的特点

class:表示Bean类型

scope:表示Bean的作用域(单例/原型)

lazyInit:表示Bean是否是懒加载

initMethodName:表示Bean初始化时要执行的方法

destroyMethodName:表示Bean销毁时要执行的方法

........

二、在Spring中,定义Bean的方式

声明式定义:

1、<bean/>

2、@Bean

3、@Component(@Service,@Controller)

编程式定义:

直接通过BeanDefinition,此处就是Spring源码定义一个Bean的实现过程

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();beanDefinition.setBeanClass(UserService.class);beanDefinition.setScope("prototype");//把beanDefinition注册到容器中context.registerBeanDefinition("userService",beanDefinition);UserService userService = (UserService)context.getBean("userService");userService.test();
 三、Spring内部的组件

下面的组件在Spring中使用的很少,但是在源码中使用的很多,学习有利于理解源码

1、AnnotatedBeanDefinitionReader

可以直接把某个类转换为BeanDefinition,并读取解析类的注解。就是BeanDefiniton读取器。把读到的BeanDefinition存到容器中

        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(context);//将UserService.class解析为BeanDefinitionannotatedBeanDefinitionReader.register(UserService.class);System.out.println(context.getBean("userService"));

2、XmlBeanDefinitionReader

可以解析<bean/>标签

          AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(context);xmlBeanDefinitionReader.loadBeanDefinitions("spring.xml");

3、ClassPathBeanDefinitionScanner

扫描器,和BeanDefinitionReader类似,对某个包路径就行扫描,对扫描的类进行解析,如果存在@Component注解,就会把这个类解析为一个BeanDefinition

       AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.refresh();ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);int i = scanner.scan("org.com.zhuyn");System.out.println(context.getBean("userService"));
四、ApplicationContext与BeanFactory

ApplicationContext继承了BeanFactory,除此之外还继承了别的

ApplicationEnventPublisher:事件发布器

EnvironmentCapable:获取环境变量的功能

MessageSource:进行国际化的功能

ResourcepatternResolver:解析某些资源的功能

因此,当我们使用applicationContext.getBean("xxx")的时候,本质上是使用的DefaultListableBeanFactory来获取的。

1、ResourcepatternResolver

(1)拿文件资源

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Resource resource = context.getResource("file://C:\\Usersxxxxxxxxx"");System.out.println(resource.contentLength());

(2)拿url

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);Resource resource = context.getResource("https://www.baidu.com");System.out.println(resource.contentLength());System.out.println(resource.getURL());

这里的Resource可以拿很多种资源。

2、ApplicationEnventPublisher

在工作当中可以直接定义一个事件发布器、

@Component
public class UserService {private ApplicationEventPublisher applicationEventPublisher;}

也可以使用applicationContext自带的事件发布器

@Component
public class UserService {@Autowiredprivate ApplicationContext context;public void test(){context.publishEvent("hello");System.out.println("test");}}

事件监听器

@ComponentScan("org.com.zhuyn")
public class AppConfig {@Beanpublic ApplicationListener applicationListener(){return new ApplicationListener() {@Overridepublic void onApplicationEvent(ApplicationEvent applicationEvent) {System.out.println("发布了一个事件"+applicationEvent);}};}
}
五、类型转化

1、PropertyEditor

把字符串转换成user对象。

类型转换器

public class StringToUserPropertyEditor extends PropertyEditorSupport implements PropertyEditor {@Overridepublic void setAsText(String text) throws IllegalArgumentException {User user = new User();user.setName(text);this.setValue(user);}
}

类型转换器的使用

        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);StringToUserPropertyEditor propertyEditor = new StringToUserPropertyEditor();propertyEditor.setAsText("xiaoming");User user = (User) propertyEditor.getValue();System.out.println(user.getName());

  在spring内部也使用到了类型转换,例如当我们使用这个

UserService userservice = context.getBean("userService",UserService.class)

我们传一个string类型,得到一个UserService类型的对象。

2、ConversionService

3、TypeConverter

六、比较器

可以根据@Order注解或实现Ordered接口来执行值进行比较,从而可以进行排序。

Ordered接口实现方法:

1、在类上实现Ordered接口

2、使用OrderComparator构建比较器

类A

public class A implements Ordered {@Overridepublic int getOrder() {return 1;}
}

类B

public class B implements Ordered {@Overridepublic int getOrder() {return 10;}
}

应用:

        A a = new A();B b = new B();OrderComparator comparator = new OrderComparator();System.out.println(comparator.compare(a, b));//-1 a大为1,b大为-1List list = new ArrayList<>();list.add(a);list.add(b);//按order值升序排序list.sort(comparator);System.out.println(list);//[org.com.zhuyn.Service.A@2f2c9b19, org.com.zhuyn.Service.B@31befd9f]

@Order注解实现方法

Spring提供了OrderComparator的子类:AnnotationAwareOrderComparator,它支持使用@Order来指定order值

类C

@Order(1)
public class C {
}

类D

@Order(10)
public class D {}

应用

        C c = new C();D d = new D();AnnotationAwareOrderComparator comparator = new AnnotationAwareOrderComparator();System.out.println(comparator.compare(c,d));//-1
七、类的元数据

在Spring中需要去解析类的信息,比如类名,类中的方法,类上的注解,这些都可以称为类的元数据。所以Spring中对类的元数据做了抽象,并提供了一些工具类。

1、MetaDataReader(类的元数据读取器)

解析一个类,得到类的所有信息。AnnotatedBeanDefinitionReader 只读取了类的注解而MetaDataReader读取了一个类的所有信息,包括类的注解,类继承了什么,类实现了哪些方法.....等等。

MetaDataReader是一个接口,默认实现类为SimpleMetadataReader。

        SimpleMetadataReaderFactory simpleMetadataReaderFactory = new SimpleMetadataReaderFactory();//构造一个MetaDataReaderMetadataReader metadataReader = simpleMetadataReaderFactory.getMetadataReader("org.com.zhuyn.Service.UserService");//得到一个ClassMetaData,并获取类名ClassMetadata classMetadata = metadataReader.getClassMetadata();System.out.println(classMetadata.getClassName());//获取接口名字,结果为一个数组System.out.println(classMetadata.getInterfaceNames()[0]);//类上注解的信息AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();for(String annotionMetadata:annotationMetadata.getAnnotationTypes()){System.out.println(annotionMetadata);}
八、过滤器

1、excludeFilters

排除类名为UserService的类,就算她上面有@component注解,也不会成为Bean

@ComponentScan(value = "org.com.zhuyn",
excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class
)
})
public class AppConfig {}

2、includeFilters

就算UserService类上没有@Component注解,它也会被扫描成为一个Bean。

@ComponentScan(value = "org.com.zhuyn",
includeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = UserService.class
)})
public class AppConfig{
}

九、FactoryBean

可以通过这个来自己创建一个Bean

相关文章:

03Spring底层架构核心概念解析

为了感谢罕哥对我工作的帮助&#xff0c;特此记录下学习过程&#xff0c;期待成为和罕哥一样优秀的人 时间&#xff1a;2024.7.13 内容&#xff1a;spring源码课程3学习记录 一、BeanDefinition BeanDefinition表示Bean的定义&#xff0c;BeanDefinition中存在很多属性用来…...

Vue学习---vue 防抖处理函数,是处理什么场景

Vue防抖处理函数是用来处理在快速连续操作中&#xff0c;只执行最后一次操作的情况。 例如&#xff0c;在输入框输入时&#xff0c;我们可能希望只在用户完成输入后进行处理&#xff0c;而不是在每次键入时都处理。(n秒后触发一次) 以下是一个简单的Vue防抖处理函数的例子&am…...

力扣爆刷第166天之TOP100五连刷96-100(单词拆分、回溯、旋转数组)

力扣爆刷第166天之TOP100五连刷96-100&#xff08;单词拆分、回溯、旋转数组&#xff09; 文章目录 力扣爆刷第166天之TOP100五连刷96-100&#xff08;单词拆分、回溯、旋转数组&#xff09;一、24. 两两交换链表中的节点二、139. 单词拆分三、560. 和为 K 的子数组四、209. 长…...

2024在线PHP加密网站源码

源码介绍 2024在线PHP加密网站源码 更新内容: 1.加强算法强度 2.优化模版UI 加密后的代码示例截图 源码下载 https://download.csdn.net/download/huayula/89568335...

网络驱动移植(RTL8189)

1、把驱动放到内核文件夹中&#xff08;linux/drivers/net/wireless&#xff09;&#xff0c;对应的驱动可以在网上下载 2、修改该目录下的Kconfig和Makefile文件 3、配置内核&#xff08;make menuconfig&#xff09; 配置支持IEEE 802.11&#xff0c;选中8189模块&#xff0…...

go语言中map学习

在 Go 语言中,map 是一种引用类型,这意味着它有以下特点: 内存结构: map 实际上是一个指向底层数据结构的指针。这个底层数据结构包含键值对的集合。 赋值与传参: 当你给一个变量赋值一个 map 时,或者将 map 作为函数参数传递时,实际上传递的是指针,而不是完整的数据结构副本。…...

【C#】| 与 及其相关例子

按位或&#xff08;|&#xff09; 按位或运算符 | 对两个数的每一位进行比较&#xff0c;如果两个数中至少有一个为 1&#xff0c;则结果位为 1&#xff1b;否则&#xff0c;结果位为0。 1010 (10 in decimal) | 1100 (12 in decimal) ------1110 (14 in decimal) 力扣相关…...

【数据结构 | 哈希表】一文了解哈希表(散列表)

&#x1f601;博客主页&#x1f601;&#xff1a;&#x1f680;https://blog.csdn.net/wkd_007&#x1f680; &#x1f911;博客内容&#x1f911;&#xff1a;&#x1f36d;嵌入式开发、Linux、C语言、C、数据结构、音视频&#x1f36d; &#x1f923;本文内容&#x1f923;&a…...

go创建对象数组

在 Go 语言中&#xff0c;可以使用字面量的方式创建结构体对象数组。以下是一个示例代码&#xff0c;展示了如何使用字面量创建一个结构体对象数组&#xff1a; package mainimport "fmt"// 定义一个结构体 type Person struct {Name stringAge intAddress Address…...

Golang | Leetcode Golang题解之第278题第一个错误的版本

题目&#xff1a; 题解&#xff1a; func firstBadVersion(n int) int {return sort.Search(n, func(version int) bool { return isBadVersion(version) }) }...

自动化网络爬虫:如何它成为提升数据收集效率的终极武器?

摘要 本文深入探讨了自动化网络爬虫技术如何彻底改变数据收集领域的游戏规则&#xff0c;揭示其作为提升工作效率的终极工具的奥秘。通过分析其工作原理、优势及实际应用案例&#xff0c;我们向读者展示了如何利用这一强大工具加速业务决策过程&#xff0c;同时保持数据收集的…...

软件测试---测试需求分析

课程目标 什么是软件测试需求 软件测试需求的必要性 如何对软件测试需求进行分析&#xff08;重点&#xff09; 课程补充 灰度测试&#xff08;基于功能&#xff09;&#xff1a;先发布部分功能&#xff0c;然后看用户的反馈&#xff0c;再去发布另外一部分的功能更新。 A/B测…...

Android11 framework 禁止三方应用通过广播开机自启动-独立方案

之前的文章Android11 framework 禁止三方应用开机自启动记录了我调试Android11应用自启动限制的全过程&#xff0c;但是之前的方案感觉还能再研究&#xff0c;所以有了这一篇文章。 这一篇文章主要探讨Android11上&#xff0c;以广播来进行自启动的应用的限制&#xff0c;极个别…...

Node:解决Error: error:0308010C:digital envelope routines::unsupported的解决方法

问题描述 在使用vuepress搭建博客的时候&#xff0c;运行项目发现报错了&#xff0c;检查了node的版本是18&#xff0c;之前用的是16或14的版本&#xff0c;现在报&#xff1a;Error: error:0308010C:digital envelope routines::unsupported错误。 查找了一些资料&#xff0…...

spring boot(学习笔记第十四课)

spring boot(学习笔记第十四课) Spring Security的密码加密&#xff0c;基于数据库认证 学习内容&#xff1a; Spring Security的密码加密基于数据库认证 1. Spring Security的密码加密 如果用户的密码保存在数据库中是以明文保存&#xff0c;对于公司的安全将是灾难性的&…...

Android 11 Unable to start/bind service

今天在Android11上发现了一个的问题&#xff0c;如果目标Service的进程没有启动&#xff0c;那么无论是bindService还是startService都没有办法拉起指定的Service。 网上查了很多资料如下: 1.目标Service 设置 android:exported"true" 2.目标Service需要声明自定义权…...

走难而正确的路并持之以恒

走难而正确的路并持之以恒 接近八月&#xff0c;台风频繁。气象台说台风“格美”今夜将至&#xff0c;往粤北走&#xff0c;而留在粤东的将是持续的高温。高温的广州&#xff0c;这几晚的天空惊喜不断&#xff0c;成片的火烧云&#xff0c;站在猎德大桥观望&#xff0c;丹红的凤…...

规范:Redis规范

在公司项目中&#xff0c;redis属于高频使用&#xff0c;在使用中&#xff0c;我们遇到了各种各样的redis问题&#xff0c;于是针对自身情况梳理了一个redis使用规范。 一、键名设计 1、key名设计 1. 禁止包含特殊字符(比如空格、换行、单双引号以及其他转义字符) 2. 建议以…...

比较 WordPress 、 Baklib 和 BetterDocs

对于希望管理其产品和服务的在线文档或知识库以支持其客户和员工的组织来说&#xff0c;市场上有太多的平台和工具。一些组织使用 WordPress 作为 Web 内容管理&#xff0c;并打算使用可用的插件。如果您是这样的组织之一&#xff0c;正在考虑使用广泛使用的 WordPress 插件之一…...

Redis 哨兵搭建

Redis哨兵(sentinel)搭建 7.2.5 文章目录 一、单节点哨兵1. 环境介绍2. 环境前准备工作3. 安装 Redis 7.2.54. redis 配置修改并且启动4.1 修改配置文件4.2 编写启动脚本 5. 开启主从5.1 开启5.2 主库实例查看主从信息 6. 创建sentinel的配置文件并启动6.1 创建配置文件6.2 启…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)

CSI-2 协议详细解析 (一&#xff09; 1. CSI-2层定义&#xff08;CSI-2 Layer Definitions&#xff09; 分层结构 &#xff1a;CSI-2协议分为6层&#xff1a; 物理层&#xff08;PHY Layer&#xff09; &#xff1a; 定义电气特性、时钟机制和传输介质&#xff08;导线&#…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

相机从app启动流程

一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...