当前位置: 首页 > 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类型,然后注册到容器中

相关文章:

  • 【esp32]VSCode-SPI控制OLED
  • 使用 Curl 和 DomCrawler 下载抖音视频链接并存储到指定文件夹
  • 定时器PWM输出
  • uniapp 模仿 Android的Menu菜单栏
  • 开源软件:释放创新的力量,改变数字世界的游戏规则
  • 基于springboot实现学生就业管理系统项目【项目源码+论文说明】计算机毕业设计
  • 绝缘栅双极型晶体管igbt短路如何用自动化软件进行测试?
  • WPS文件恢复怎么做?记得掌握这5个方法!
  • 英飞凌TC3xx-Overlay
  • 多模态论文学习之ALBEF(Align BEfore Fusing)
  • 京东h5st逆向 python代码算法还原逆向分析 h5st代码
  • SpringMVC Day 10 : 拦截器
  • 最小化安装移动云大云操作系统--BCLinux-R8-U2-Server-x86_64-231017版
  • 【嵌入式开发学习】__hex文件、bin文件、axf文件的区别
  • Mybatis—XML配置文件、动态SQL
  • [nginx文档翻译系列] 控制nginx
  • 【React系列】如何构建React应用程序
  • 0x05 Python数据分析,Anaconda八斩刀
  • Android Studio:GIT提交项目到远程仓库
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • Quartz初级教程
  • Web设计流程优化:网页效果图设计新思路
  • 工作踩坑系列——https访问遇到“已阻止载入混合活动内容”
  • 基于Mobx的多页面小程序的全局共享状态管理实践
  • 使用API自动生成工具优化前端工作流
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • 在electron中实现跨域请求,无需更改服务器端设置
  • MPAndroidChart 教程:Y轴 YAxis
  • 长三角G60科创走廊智能驾驶产业联盟揭牌成立,近80家企业助力智能驾驶行业发展 ...
  • # 安徽锐锋科技IDMS系统简介
  • #HarmonyOS:软件安装window和mac预览Hello World
  • (五)网络优化与超参数选择--九五小庞
  • (原創) 如何刪除Windows Live Writer留在本機的文章? (Web) (Windows Live Writer)
  • (转)IOS中获取各种文件的目录路径的方法
  • ./configure,make,make install的作用(转)
  • .bat批处理(十):从路径字符串中截取盘符、文件名、后缀名等信息
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .net core 6 集成和使用 mongodb
  • .NET Framework杂记
  • .net操作Excel出错解决
  • .NET导入Excel数据
  • .Net中的集合
  • @Async注解的坑,小心
  • @RequestMapping用法详解
  • [ 云计算 | AWS 实践 ] 基于 Amazon S3 协议搭建个人云存储服务
  • [.NET]桃源网络硬盘 v7.4
  • [AX]AX2012开发新特性-禁止表或者表字段
  • [ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-controller-manager失败
  • [GN] Vue3.2 快速上手 ---- 核心语法2
  • [LeetBook]【学习日记】数组内乘积
  • [NOI2022] 众数 题解
  • [NSSCTF 2nd] web刷题记录
  • [OPEN SQL] 修改数据