Spring底层原理(四)
Spring底层原理(四)
本章内容
模拟实现Spring中的几个常见BeanFactory后置处理器
常见的BeanFactory后置处理器
GenericApplicationContext context = new GenericApplicationContext();
context.registerBean("config",Config.class);
context.registerBean(ConfigurationClassPostProcessor.class);//解析@ComponentScan @Bean @Import @ImportResource
ontext.registerBean(MapperScannerConfigurer.class,bd->{bd.getPropertyValues().add("basePackage","com.vmware.mapper");
});
//初始化容器
context.refresh();
for (String name : context.getBeanDefinitionNames()) {System.out.println(name);
}
context.close();
ConfigurationClassPostProcessor:解析@ComponentScan@Bean@Import@ImportResourceMapperScannerConfigurer:解析@Mapper
模拟实现组件扫描
- 创建一个
BeanFactoryPostProcessor的实现类
public class ComponentScanPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {ComponentScan componentScan = AnnotationUtils.findAnnotation(Config.class, ComponentScan.class);try {if (componentScan != null) {for (String basePackage : componentScan.basePackages()) {System.out.println(basePackage);String path = "classpath*:" + basePackage.replace(".", "/") + "/**/*.class";System.out.println(path);//用于获取元数据的工具类CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();//用于生成bean名称的工具AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();Resource[] resources = new PathMatchingResourcePatternResolver().getResources(path);for (Resource resource : resources) {MetadataReader metadataReader = factory.getMetadataReader(resource);//根据resource获取元数据读取器AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
// ClassMetadata classMetadata = metadataReader.getClassMetadata();
// System.out.println("类名:" + classMetadata.getClassName());
// //判读是否有注解@Component
// boolean hasComponent = metadataReader.getAnnotationMetadata().hasAnnotation(Component.class.getName());
// System.out.println("包含注解Component:" + hasComponent);
// boolean hasMetaAnnotation = metadataReader.getAnnotationMetadata().hasMetaAnnotation(Component.class.getName());
// System.out.println("元注解中包含Component:"+hasMetaAnnotation);if (annotationMetadata.hasAnnotation(Component.class.getName()) || annotationMetadata.hasMetaAnnotation(Component.class.getName())) {//构建beanDefinition对象AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(metadataReader.getClassMetadata().getClassName()).getBeanDefinition();if (configurableListableBeanFactory instanceof DefaultListableBeanFactory) {//获取容器DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;//生成bean nameString name = generator.generateBeanName(bd, beanFactory);//注册beanbeanFactory.registerBeanDefinition(name, bd);}}}}}} catch (Exception e) {e.printStackTrace();}}
}
-
注册该后置处理器
context.registerBean(ComponentScanPostProcessor.class);
模拟实现@Bean
public class AtBeanPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {try {CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();MetadataReader reader = factory.getMetadataReader(new ClassPathResource("com/vmware/a5/Config.class"));Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());for (MethodMetadata method : methods) {BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();//Bean的名称由方法名生成,除此之外还需要一个工厂Bean对象builder.setFactoryMethodOnBean(method.getMethodName(), "config");builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);AbstractBeanDefinition bd = builder.getBeanDefinition();if (configurableListableBeanFactory instanceof DefaultListableBeanFactory) {DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;beanFactory.registerBeanDefinition(method.getMethodName(), bd);}}} catch (IOException e) {e.printStackTrace();}}
}
模拟实现Mapper扫描
public class MapperPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanFactory) throws BeansException {try {PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();Resource[] resources = resolver.getResources("classpath:com/vmware/a5/mapper/**/*.class");AnnotationBeanNameGenerator generator = new AnnotationBeanNameGenerator();CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();for (Resource resource : resources) {MetadataReader reader = factory.getMetadataReader(resource);//获取类元数据ClassMetadata classMetadata = reader.getClassMetadata();//过滤接口类型if (classMetadata.isInterface()){AbstractBeanDefinition bd = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class).addConstructorArgValue(classMetadata.getClassName())//构造方法需要对应的接口字节码.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE)//需要对MapperFactory进行注入.getBeanDefinition();//根据接口名称重新生成一个bean,仅用于生成mapper的名称,否则所有名称都是MapperFactoryBeanAbstractBeanDefinition bd2 = BeanDefinitionBuilder.genericBeanDefinition(classMetadata.getClassName()).getBeanDefinition();String name = generator.generateBeanName(bd2, beanFactory);beanFactory.registerBeanDefinition(name,bd);}}}catch (Exception e){e.printStackTrace();}}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {}
}
- 将Mapper封装成
MapperFactoryBean类型,然后注册到容器中
相关文章:
Spring底层原理(四)
Spring底层原理(四) 本章内容 模拟实现Spring中的几个常见BeanFactory后置处理器 常见的BeanFactory后置处理器 GenericApplicationContext context new GenericApplicationContext(); context.registerBean("config",Config.class); context.registerBean(Conf…...
Android 14 rook替代Postern进行中间人抓包
以下是关于使用Brook替代Postern进行中间人抓包的说明: 先来解释下,为什么用Postern而不用fd,fd属于代理抓包。Postern属于是模拟出来一张虚拟网卡抓包。性质不一样,所以害怕大哥问我。我就先放在这里 在Android 14及之前的版本中…...
[rancher] rancher部署和使用的一些思考
最近因为工作需要,学习调研rancher的使用 k8s作为主流微服务部署的基础,已经逐渐在工作中普及。但是k8s dashboard用于生产管理,还是有所欠缺:我们需要一个k8s之上的管理平台。经过调研,目前rancher已经迭代开发至v2.8…...
迅镭激光董事长颜章健荣膺“2023年如皋市科技强企人物”!
10月28日,2023如皋科技人才洽谈会开幕式在如皋隆重举行。江苏省科学技术厅副厅长、党组成员蒋洪,江苏省商务厅副厅长、党组成员孙津,中共南通市委副书记、政法委书记沈雷,中共如皋市市委书记何益军,中共如皋市委副书记…...
专业医学病例翻译公司推荐
我们知道,医学病例翻译在涉外看病的患者中具有广泛的应用,它可以帮助医生快速了解患者的病情,为治疗和药物处方提供关键信息。因此,对于出国看病的患者,医学病例翻译便成了不可或缺的重要工具。 翻译医学病例不仅要求译…...
英飞凌TC3xx-Overlay
目录 1.数据访问重定向 2.寄存器说明 3.Overlay功能配置 3.1 确认用于重定向的CPU 3.2 配置重定向Block大小 3.3 配置目标地址和重定向地址 4.结果验证 5.小结 今天说要开个专栏讲讲XCP标定,但在将标定之前,先把英飞凌专门为标定功能设计overlay…...
Win10系统有几种复制文件的命令,哪种最强大?
环境: Win10 专业版 问题描述: Win10系统有几种复制文件的命令,哪种最强大? 解决方案: 在 Windows 10 中,复制文件的命令有以下几种: 使用 xcopy 命令:xcopy 是一个功能强大的…...
力扣202.快乐数
原题链接:202.快乐数 要记住的就是,需要判断元素是否出现过,或者是否在集合里存在,就可以考虑用哈希法去做 因为是每一位都进行平方后相加得到新的数,所以需要单独写一个函数进行每位相加的运算得到最终的sum 不断重…...
iOS Xcode15 适配:Other Linker Flags:-ld_classic
0x00 适配是一条没有尽头的路 Xcode 14 毛问题都没有,Xcode 15 崩溃 看图说话 0x01 解决方案 Other Linker Flags 添加 -ld_classic 即可 0x02 我的小作品 欢迎体验我的作品之一:小挑战-XGame 拼图游戏,渐变色游戏,经典24点游…...
springboot苍穹外卖实战:六、redis(Spring Data Redis)
Spring Data Redis 简介 网址:https://spring.io/projects/spring-data-redis Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下࿱…...
sqli 靶场 Level23-Level30 wp
level-23 (注释被过滤) 抓包,查看正常请求和响应。 略 尝试是否存在注入 id1’,id1’,成周期性变化 尝试 POC POC: id1andextractValue(1,concat(0x7e,user()))-- 结果:failed。怀疑–被过滤掉了,尝试…...
《完蛋!我被美女包围了》突然火了!世界首个开源贡献榜出炉丨 RTE 开发者日报 Vol.75
开发者朋友们大家好: 这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE (Real Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…...
C++ Qt 学习(一):Qt 入门
Qt6 安装教程 0. 基础知识 0.1 qmake 和 cmake 对比 qmake:qt 独有的代码构建工具cmake:C 通用的代码构建工具,绝大部分 C 开源项目都使用 cmake 管理代码qt 项目,没有特殊要求,使用 qmake 即可 0.2 Qt 3 个窗口类的…...
高性能消息中间件 - Kafka3.x(三)
文章目录 高性能消息中间件 - Kafka3.x(三)Kafka Broker ⭐Kafka Broker概念Zookeeper(新版本可以不使用zk了)⭐Zookeeper的作用 Kafka的选举1:Broker选举Leader⭐Broker核心参数⭐案例:服役新节点和退役旧…...
【八】Linux成神之路
Linux成神之路 简介:最近梳理了一下自己linux系统的学习历程,感觉整个成长过程就很顺利,并没有走弯路,于是想着可以不可以把自己linux系统学习的路线记录下来,能够在大家成长的路上有一点帮助,就在这样的一…...
功能测试用例,需要详细到什么程度?
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...
VScode远程连接错误:进程试图写入不存在的管道
使用VScode连接树莓派时,出现远程连接错误:进程试图写入不存在的管道 解决方案: (1)可以进入config所在文件夹,删除文件 (2)无法解决的化尝试下述方法 输入 Remotting-SSH:Settin…...
Python测试之Pytest详解
概要 当涉及到python的测试框架时,pytest是一个功能强大且广泛应用的第三方库。它提供简洁而灵活的方式来编写和执行测试用例,并具有广泛的应用场景。下面是pytest的介绍和详细使用说明: pytest是一个用于python单元测试的框架,它…...
uni-app微信小程序打开第三方地图
需求 小程序中有个按钮点击以后会调用手机中第三方地图进行导航。参数 位置信息 经度 与纬度。 实现方法 uni.openLocation({latitude: Number(地址纬度),longitude: Number(地址经度),name: 地址名称,address: 地址详情,success: function (res) {console.log(打开系统位置地…...
Android NDK开发详解之NDK 使用入门
Android NDK开发详解之NDK 使用入门 下载 NDK 和工具创建或导入原生项目 原生开发套件 (NDK) 是一套工具,使您能够在 Android 应用中使用 C 和 C 代码,并提供众多平台库,您可使用这些平台库管理原生 activity 和访问实体设备组件,…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
Qt/C++开发监控GB28181系统/取流协议/同时支持udp/tcp被动/tcp主动
一、前言说明 在2011版本的gb28181协议中,拉取视频流只要求udp方式,从2016开始要求新增支持tcp被动和tcp主动两种方式,udp理论上会丢包的,所以实际使用过程可能会出现画面花屏的情况,而tcp肯定不丢包,起码…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
