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

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 @ImportResource
  • MapperScannerConfigurer:解析@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进行中间人抓包的说明&#xff1a; 先来解释下&#xff0c;为什么用Postern而不用fd&#xff0c;fd属于代理抓包。Postern属于是模拟出来一张虚拟网卡抓包。性质不一样&#xff0c;所以害怕大哥问我。我就先放在这里 在Android 14及之前的版本中…...

[rancher] rancher部署和使用的一些思考

最近因为工作需要&#xff0c;学习调研rancher的使用 k8s作为主流微服务部署的基础&#xff0c;已经逐渐在工作中普及。但是k8s dashboard用于生产管理&#xff0c;还是有所欠缺&#xff1a;我们需要一个k8s之上的管理平台。经过调研&#xff0c;目前rancher已经迭代开发至v2.8…...

迅镭激光董事长颜章健荣膺“2023年如皋市科技强企人物”!

10月28日&#xff0c;2023如皋科技人才洽谈会开幕式在如皋隆重举行。江苏省科学技术厅副厅长、党组成员蒋洪&#xff0c;江苏省商务厅副厅长、党组成员孙津&#xff0c;中共南通市委副书记、政法委书记沈雷&#xff0c;中共如皋市市委书记何益军&#xff0c;中共如皋市委副书记…...

专业医学病例翻译公司推荐

我们知道&#xff0c;医学病例翻译在涉外看病的患者中具有广泛的应用&#xff0c;它可以帮助医生快速了解患者的病情&#xff0c;为治疗和药物处方提供关键信息。因此&#xff0c;对于出国看病的患者&#xff0c;医学病例翻译便成了不可或缺的重要工具。 翻译医学病例不仅要求译…...

英飞凌TC3xx-Overlay

目录 1.数据访问重定向 2.寄存器说明 3.Overlay功能配置 3.1 确认用于重定向的CPU 3.2 配置重定向Block大小 3.3 配置目标地址和重定向地址 4.结果验证 5.小结 今天说要开个专栏讲讲XCP标定&#xff0c;但在将标定之前&#xff0c;先把英飞凌专门为标定功能设计overlay…...

Win10系统有几种复制文件的命令,哪种最强大?

环境&#xff1a; Win10 专业版 问题描述&#xff1a; Win10系统有几种复制文件的命令&#xff0c;哪种最强大&#xff1f; 解决方案&#xff1a; 在 Windows 10 中&#xff0c;复制文件的命令有以下几种&#xff1a; 使用 xcopy 命令&#xff1a;xcopy 是一个功能强大的…...

力扣202.快乐数

原题链接&#xff1a;202.快乐数 要记住的就是&#xff0c;需要判断元素是否出现过&#xff0c;或者是否在集合里存在&#xff0c;就可以考虑用哈希法去做 因为是每一位都进行平方后相加得到新的数&#xff0c;所以需要单独写一个函数进行每位相加的运算得到最终的sum 不断重…...

iOS Xcode15 适配:Other Linker Flags:-ld_classic

0x00 适配是一条没有尽头的路 Xcode 14 毛问题都没有&#xff0c;Xcode 15 崩溃 看图说话 0x01 解决方案 Other Linker Flags 添加 -ld_classic 即可 0x02 我的小作品 欢迎体验我的作品之一&#xff1a;小挑战-XGame 拼图游戏&#xff0c;渐变色游戏&#xff0c;经典24点游…...

springboot苍穹外卖实战:六、redis(Spring Data Redis)

Spring Data Redis 简介 网址&#xff1a;https://spring.io/projects/spring-data-redis Spring Data Redis中提供了一个高度封装的类&#xff1a;RedisTemplate&#xff0c;对相关api进行了归类封装,将同一类型操作封装为operation接口&#xff0c;具体分类如下&#xff1…...

sqli 靶场 Level23-Level30 wp

level-23 &#xff08;注释被过滤&#xff09; 抓包&#xff0c;查看正常请求和响应。 略 尝试是否存在注入 id1’,id1’&#xff0c;成周期性变化 尝试 POC POC: id1andextractValue(1,concat(0x7e,user()))-- 结果&#xff1a;failed。怀疑–被过滤掉了&#xff0c;尝试…...

《完蛋!我被美女包围了》突然火了!世界首个开源贡献榜出炉丨 RTE 开发者日报 Vol.75

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE &#xff08;Real Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…...

C++ Qt 学习(一):Qt 入门

Qt6 安装教程 0. 基础知识 0.1 qmake 和 cmake 对比 qmake&#xff1a;qt 独有的代码构建工具cmake&#xff1a;C 通用的代码构建工具&#xff0c;绝大部分 C 开源项目都使用 cmake 管理代码qt 项目&#xff0c;没有特殊要求&#xff0c;使用 qmake 即可 0.2 Qt 3 个窗口类的…...

高性能消息中间件 - Kafka3.x(三)

文章目录 高性能消息中间件 - Kafka3.x&#xff08;三&#xff09;Kafka Broker ⭐Kafka Broker概念Zookeeper&#xff08;新版本可以不使用zk了&#xff09;⭐Zookeeper的作用 Kafka的选举1&#xff1a;Broker选举Leader⭐Broker核心参数⭐案例&#xff1a;服役新节点和退役旧…...

【八】Linux成神之路

Linux成神之路 简介&#xff1a;最近梳理了一下自己linux系统的学习历程&#xff0c;感觉整个成长过程就很顺利&#xff0c;并没有走弯路&#xff0c;于是想着可以不可以把自己linux系统学习的路线记录下来&#xff0c;能够在大家成长的路上有一点帮助&#xff0c;就在这样的一…...

功能测试用例,需要详细到什么程度?

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…...

VScode远程连接错误:进程试图写入不存在的管道

使用VScode连接树莓派时&#xff0c;出现远程连接错误&#xff1a;进程试图写入不存在的管道 解决方案&#xff1a; &#xff08;1&#xff09;可以进入config所在文件夹&#xff0c;删除文件 &#xff08;2&#xff09;无法解决的化尝试下述方法 输入 Remotting-SSH:Settin…...

Python测试之Pytest详解

概要 当涉及到python的测试框架时&#xff0c;pytest是一个功能强大且广泛应用的第三方库。它提供简洁而灵活的方式来编写和执行测试用例&#xff0c;并具有广泛的应用场景。下面是pytest的介绍和详细使用说明&#xff1a; pytest是一个用于python单元测试的框架&#xff0c;它…...

uni-app微信小程序打开第三方地图

需求 小程序中有个按钮点击以后会调用手机中第三方地图进行导航。参数 位置信息 经度 与纬度。 实现方法 uni.openLocation({latitude: Number(地址纬度),longitude: Number(地址经度),name: 地址名称,address: 地址详情,success: function (res) {console.log(打开系统位置地…...

Android NDK开发详解之NDK 使用入门

Android NDK开发详解之NDK 使用入门 下载 NDK 和工具创建或导入原生项目 原生开发套件 (NDK) 是一套工具&#xff0c;使您能够在 Android 应用中使用 C 和 C 代码&#xff0c;并提供众多平台库&#xff0c;您可使用这些平台库管理原生 activity 和访问实体设备组件&#xff0c;…...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

OpenLayers 分屏对比(地图联动)

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能&#xff0c;和卷帘图层不一样的是&#xff0c;分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

给网站添加live2d看板娘

给网站添加live2d看板娘 参考文献&#xff1a; stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下&#xff0c;文章也主…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...