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

手写@MapperScan

  • 定义一个EnableMapperScan注解
    @Import(MapperProxyHandlerRegister.class) 标注将MapperProxyHandlerRegister导入到容器中。
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Import(MapperProxyHandlerRegister.class)
public @interface EnableMapperScan {String baskPackages();}
  • MapperProxyHandlerRegister

ImportBeanDefinitionRegistrar 是一个特殊组件,实现了这个接口的组件registry会动态给容器中批量注册组件,这里的关键就是获取到baskPackages 指定的路径,然后批量扫描classpath下的所有的接口,然后定义BeanDefinition,注册到容器中。
注意:AnnotationMetadata metadata封装的是标注了@Import注解的那个类。这样就可以拿到最终因哪个类扫描的这个配置类。

/*** Mapper组件注册器*/
public class MapperProxyHandlerRegister implements ImportBeanDefinitionRegistrar {/*** @param metadata  注意:metadata是Spring解析@Import注解标注的那个类的元信息,而不是导入的配置类的元信息* @param registry  BeanDefinition注册器* @param generator BeanName生成器*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry,BeanNameGenerator generator) {//这里的这个metadata封装的是标注了@Import注解的那个类,如果标注@Import注解因其他类似@Enablexxx注解进一步解析到的//那这里的metadata封装的就是解析@Enablexxx那个类的元数据信息,//总之,metadata封装的就是Spring原始解析类上关联的@Import注解的类Map<String, Object> annotationAttributes = metadata.getAnnotationAttributes(EnableMapperScan.class.getName());String baskPackages = annotationAttributes.get("baskPackages").toString();//获取此包下所有的类try {Set<Class<?>> scan = scan(baskPackages);if (CollUtil.isNotEmpty(scan)){//遍历接口for (Class<?> mapperClass : scan) {//注册到容器RootBeanDefinition definition = new RootBeanDefinition();definition.setBeanClass(MapperFactoryBean.class);//设置构造方法参数值ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();constructorArgumentValues.addIndexedArgumentValue(0,mapperClass);definition.setConstructorArgumentValues(constructorArgumentValues);//definition.setFactoryMethodName("getObject");//注册Beanregistry.registerBeanDefinition(mapperClass.getName(),definition);}}} catch (Exception e) {e.printStackTrace();}}/*1. 创建A   --> 依赖B --> 创建B(依赖A) -> 为A创建代理对象 ,并从缓存中拿,后注入A的是一个代理对象。* */public static Set<Class<?>> scan(String basePackage) throws IOException, ClassNotFoundException {// 创建一个扫描器//ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);// 可以添加过滤器来筛选特定类型的类,这里先不添加任何过滤器,获取所有类// 例如,如果只想获取带有特定注解的类,可以添加如下代码// scanner.addIncludeFilter(new AnnotationTypeFilter(YourAnnotation.class));// 如果只想获取特定接口的实现类,可以添加如下代码// scanner.addIncludeFilter(new AssignableTypeFilter(YourInterface.class));// 构建要扫描的资源路径模式ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +resolveBasePackage(basePackage) + "/**/*.class";Resource[] resources = resolver.getResources(packageSearchPath);MetadataReaderFactory metadataReaderFactory = new SimpleMetadataReaderFactory();Set<Class<?>> classes = new HashSet<>();for (Resource resource : resources) {MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);String sourceClassName = metadataReader.getClassMetadata().getClassName();if (metadataReader.getClassMetadata().isInterface()){//只扫描mapper接口classes.add(Class.forName(sourceClassName));}//System.out.println("sourceClassName = " + sourceClassName);// 排除接口和抽象类,只获取具体类//if (!metadataReader.getClassMetadata().isInterface() &&!metadataReader.getClassMetadata().isAbstract()) {//    String className = metadataReader.getClassMetadata().getClassName();//    classes.add(Class.forName(className));//}}return classes;}private static String resolveBasePackage(String basePackage) {return basePackage.replace('.', '/');}
  • MapperProxy

这个类封装了代理对象的核心方法,主要就是获取mapper接口上标注了@Select @Update @Delete注解的方法,解析sql参数,获取sqlsessionfactory,然后执行sql。这里简单模拟输出获取到的sql。

/**mapper组件动态代理方法拦截实现*/
public class MapperProxy implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getDeclaringClass() == Object.class){return method.invoke(this,args);}String name = method.getDeclaringClass().getName();String methodName = method.getName();System.out.println("mapperProxy 执行方法,被代理对象拦截 ===》 " + name + "." +methodName + "()");Select select = method.getAnnotation(Select.class);if (select != null){String[] value = select.value();//拦截方法System.out.println("拦截到的SQL:===> " + Arrays.toString(value));}Class<?> returnType = method.getReturnType();if (Number.class.isAssignableFrom(returnType) || returnType.isPrimitive()){return 1;}return null;}
}
  • MapperFactoryBean

这个类实现了FactoryBean 接口,实现了这个接口的类Spring会进一步调用getObject方法创建Bean对象,这个Bean对象的类型是getObjectType返回的数据类型,由此,这个类型就是真正的Mapper接口类型,可以实现基于Mapper接口的自动装配。

public class MapperFactoryBean implements FactoryBean {private Class mapperInterFaceClazz;public MapperFactoryBean(Class mapperInterFaceClazz){this.mapperInterFaceClazz = mapperInterFaceClazz;}@Overridepublic Object getObject() throws Exception {/**在创建代理对象时,传入需要实现的接口mapperInterFaceClazz如果这个接口还继承了其他接口,在基于实现类调方法时,父接口的方法也会被代理对象拦截。原理很简单,面向对象三大特征之一: 继承,子类继承父类,就把父类所有的内容全都继承JVM在判断时,如果满足继承结构以及安全检查*/return Proxy.newProxyInstance(mapperInterFaceClazz.getClassLoader(),new Class[]{mapperInterFaceClazz},new MapperProxy());}@Overridepublic Class<?> getObjectType() {return mapperInterFaceClazz;}}
  • MainApp
@SpringBootApplication
@EnableMapperScan(baskPackages = "com.example.ssm3.mapper")

相关文章:

手写@MapperScan

定义一个EnableMapperScan注解 Import(MapperProxyHandlerRegister.class) 标注将MapperProxyHandlerRegister导入到容器中。 Target({ElementType.METHOD,ElementType.TYPE}) Retention(RetentionPolicy.RUNTIME) Import(MapperProxyHandlerRegister.class) public interface…...

【C++】深入理解迭代器(Iterator)

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;什么是迭代器&#xff1f;迭代器与指针的比较 &#x1f4af;std::string 中的迭代器示例代码与图示分析运行结果&#xff1a;图示说明&#xff1a; 小提示 &#x1f4af;正…...

后端Java开发:第十二天

第十二天&#xff1a;封装 - 理解与应用 欢迎来到今天的学习内容&#xff01;今天&#xff0c;我们将一起深入探讨 Java 中的 封装&#xff08;Encapsulation&#xff09;。封装是面向对象编程的四大基本特性之一&#xff0c;它的核心思想是把对象的状态&#xff08;属性&…...

记录一下Coding一直不能clone

配置 下载git客户端&#xff0c;进行配置 git config --list user.name姓名全称 user.emailIAM_xxxxxx.com ,这个就是你的邮箱地址 user.signingkey 注册coding平台的密码 一般不需要配置公钥私钥 下载TortoiseGit&#xff0c;配置这几个参数 配置凭据管理器 注意 这里用户名是…...

LLM加速方法,Adapter Tuning和Prompt Tuning的区别及原理举例

LLM加速方法 目录 LLM加速方法整体结构各分支内容Adapter Tuning和Prompt Tuning的区别及原理举例一、区别二、总结整体结构 基于模型微调、基于模型压缩、基于分布式并行处理。 各分支内容 基于模型微调: 包含Adapter Tuning、Prompt Tuning、LoRA三个子类别。这些技术主要…...

【SVN】版本发布快捷操作

摘要&#xff1a;因为每次发版都需要制作一份相同的文件夹&#xff0c;而大部分的包都不需要变更&#xff0c;但是文件又非常大&#xff0c;记录自己的操作经验。 首先在SVN Repository Browser 界面把上一次的版本复制一份&#xff0c;复制的时候重命名为新的版本号 右击要复…...

GitLab 创建项目、删除项目

1、创建项目 点击左上角图标&#xff0c;回到首页 点击 Create a project 点击 Create blank project 输入项目名称&#xff0c;点击Create Project 创建成功 2、删除项目 进入项目列表 点击对应项目&#xff0c;进入项目 进入Settings页面 拖到页面底部&#xff0c;展开Adva…...

STM32-笔记37-吸烟室管控系统项目

一、项目需求 1. 使用 mq-2 获取环境烟雾值&#xff0c;并显示在 LCD1602 上&#xff1b; 2. 按键修改阈值&#xff0c;并显示在 LCD1602 上&#xff1b; 3. 烟雾值超过阈值时&#xff0c;蜂鸣器长响&#xff0c;风扇打开&#xff1b;烟雾值小于阈值时&#xff0c;蜂鸣器不响…...

VisionPro软件Image Stitch拼接算法

2D图像拼接的3种情景 1.一只相机取像位置固定&#xff0c;或者多只相机固定位置拍图&#xff0c;硬拷贝拼图&#xff0c;采用CopyRegion工具实现 2.一只或多只相机在多个位置拍照&#xff0c;相机视野互相重叠&#xff0c;基于Patmax特征定位后&#xff0c;无缝 拼图&#xff…...

【从零开始入门unity游戏开发之——unity篇09】unity6基础入门——Unity游戏对象和组件的本质、Unity中的反射机制

文章目录 一、Unity游戏对象和组件的本质1、开发游戏的本质2、万物之根本——空对象2.1 什么是空对象&#xff1f;2.2 创建空对象 3、Unity游戏对象的本质4、 transform组件4.1 transform组件的重要性4.2 修改transform的值4.4 **Transform的作用**4.3 重置transform的值 5、总…...

【Linux】深入理解文件系统(超详细)

目录 一.磁盘 1-1 磁盘、服务器、机柜、机房 &#x1f4cc;补充&#xff1a; &#x1f4cc;通常网络中用高低电平&#xff0c;磁盘中用磁化方向来表示。以下是具体说明&#xff1a; &#x1f4cc;如果有一块磁盘要进行销毁该怎么办&#xff1f; 1-2 磁盘存储结构 ​编辑…...

MoEs and Transformers 笔记

ref:https://huggingface.co/blog/zh/moe#%E7%94%A8router-z-loss%E7%A8%B3%E5%AE%9A%E6%A8%A1%E5%9E%8B%E8%AE%AD%E7%BB%83 MoEs and Transformers Transformer 类模型明确表明&#xff0c;增加参数数量可以提高性能&#xff0c;因此谷歌使用 GShard 尝试将 Transformer 模型…...

在Linux中,如何禁用root用户直接SSH登录?

在Linux中禁用root用户的直接SSH登录是为了增强系统的安全性&#xff0c;因为允许root用户通过SSH远程登录会增加服务器被暴力破解的风险。以下是在Linux系统中禁止root用户直接SSH登录的步骤&#xff1a; 编辑SSH配置文件&#xff1a; 打开/etc/ssh/sshd_config文件&#xff…...

用Python实现简单的任务自动化

目录 1. 自动发送邮件提醒 2. 自动备份文件 3. 自动下载网页内容 总结 在现代工作和生活中,任务自动化可以极大地提高效率和准确性。Python,作为一种功能强大且易于学习的编程语言,是实现任务自动化的理想选择。本文将通过几个简单而实用的案例,展示如何用Python实现任…...

为AI聊天工具添加一个知识系统 之26 资源存储库和资源管理器

本文要点 资源存储库 为了能完成本项目&#xff08;“为AI聊天工具增加一个知识系统”&#xff0c;其核心能力是“语言处理” &#xff0c;该能力的最大挑战 当仁不让的应该是自然语言处理&#xff09;的设计&#xff0c;我们考虑一个问题&#xff1a;在自然语言处理中&#…...

Windows10环境下安装RabbitMq折腾记

最近有个老项目需要迁移到windows10环境&#xff0c;用的是比较老的rabbitmq安装包&#xff0c;如下所示。经过一番折腾&#xff0c;死活服务起不来&#xff0c;最终果断放弃老版本启用新版本。现在把折腾过程记录下&#xff1a; 一、安装erlang 安装完成后的目录结构&#xff…...

对快速由表及里说拜拜/如何正确运用由表及里

你是不是还&#xff1a;看到一男子拖走一女子就以为小情侣吵架而已&#xff08;可能人贩子&#xff09;&#xff1b;看到男友对你好个几次就从此死心塌地&#xff08;可能有手就行&#xff0c;细节装装而已&#xff09;结果耽误终身&#xff1b;看到女同事对你微笑不排斥就以为…...

spring mvc源码学习笔记之八

本文说点儿简单的。 如果你想研究基于 XML 配置的 spring mvc 的话&#xff0c;可以简单扫一眼本文。 在基于 XML 配置的 spring mvc 开发中&#xff0c;我们主要就是通过 spring 提供的各种标签来配置。 但是&#xff0c;大家是不是都有个疑问&#xff0c;spring 到底给我们提…...

探秘5网口IIOT网关

在当今这个科技飞速发展的时代&#xff0c;工业领域正经历着一场深刻的变革&#xff0c;而工业物联网网关在其中扮演着至关重要的角色。 什么是IIOT网关 工业物联网网关&#xff0c;简单来说&#xff0c;就是连接工业现场设备与云端或者上层管理系统的关键桥梁。 而明达技术研…...

左神算法基础巩固--5

文章目录 前缀树生成前缀树查询前缀树查询字符串加入过几次查询所有加入的字符串中&#xff0c;有几个是以pre这个字符串作为前缀 删除前缀树中的某个字符串 贪心算法解题 前缀树 生成前缀树 要想生成一棵前缀树&#xff0c;需要先创建一个根节点&#xff0c;这个根节点有26条…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

怎么让Comfyui导出的图像不包含工作流信息,

为了数据安全&#xff0c;让Comfyui导出的图像不包含工作流信息&#xff0c;导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo&#xff08;推荐&#xff09;​​ 在 save_images 方法中&#xff0c;​​删除或注释掉所有与 metadata …...

BLEU评分:机器翻译质量评估的黄金标准

BLEU评分&#xff1a;机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域&#xff0c;衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标&#xff0c;自2002年由IBM的Kishore Papineni等人提出以来&#xff0c;…...

【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验

Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...

AxureRP-Pro-Beta-Setup_114413.exe (6.0.0.2887)

Name&#xff1a;3ddown Serial&#xff1a;FiCGEezgdGoYILo8U/2MFyCWj0jZoJc/sziRRj2/ENvtEq7w1RH97k5MWctqVHA 注册用户名&#xff1a;Axure 序列号&#xff1a;8t3Yk/zu4cX601/seX6wBZgYRVj/lkC2PICCdO4sFKCCLx8mcCnccoylVb40lP...

多模态大语言模型arxiv论文略读(112)

Assessing Modality Bias in Video Question Answering Benchmarks with Multimodal Large Language Models ➡️ 论文标题&#xff1a;Assessing Modality Bias in Video Question Answering Benchmarks with Multimodal Large Language Models ➡️ 论文作者&#xff1a;Jea…...

RK3568项目(七)--uboot系统之外设与PMIC详解

目录 一、引言 二、按键 ------>2.1、按键种类 ------------>2.1.1、RESET ------------>2.1.2、UPDATE ------------>2.1.3、PWRON 部分 ------------>2.1.4、RK809 PMIC ------------>2.1.5、ADC按键 ------------>2.1.6、ADC按键驱动 ------…...

ubuuntu24.04 编译安装 PostgreSQL15.6+postgis 3.4.2 + pgrouting 3.6.0 +lz4

文章目录 下载基础包下载源码包编译 PG编译 postgis编译安装 pgrouting下载源码包配置编译参数编译安装 初始化数据库建表并检查列是否使用了 lz4 压缩算法检查 postgis 与 pgrouting 是否可以成功创建 下载基础包 sudo apt update && sudo apt upgrade -y sudo apt i…...