Mybatis Invoker

2023-11-11 12:38
文章标签 mybatis invoker

本文主要是介绍Mybatis Invoker,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Mybatis中的Invoker对反射API中的Field.get () Fielid.get()  Method.invoke()三个方法进行了二次封装,将一些模板式的代码封装了起来,在新的版本中,还加入了安全检查。

其结构如下:

接口定义:

/*** @author Clinton Begin*/
public interface Invoker {Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;Class<?> getType();
}

接口定义较为简单,我们来看看它的实现类,先看GetFieldInvoker:

/*** @author Clinton Begin* 对field的get(获取属性值)操作进行增强,增加了强吻(private修饰的属性通过设置setAccessible方法来强行操作)机制* 之所以不用getter方法可能是为了强吻,即不提供getter方法我也可以强制访问*/
public class GetFieldInvoker implements Invoker {private final Field field;public GetFieldInvoker(Field field) {this.field = field;}@Overridepublic Object invoke(Object target, Object[] args) throws IllegalAccessException {try {return field.get(target);} catch (IllegalAccessException e) {if (Reflector.canControlMemberAccessible()) {field.setAccessible(true);return field.get(target);} else {throw e;}}}@Overridepublic Class<?> getType() {return field.getType();}

GetFiledInvoker,乍一看,还以为是操作getter方法,仔细观察发现它操作的是Field,而非 Method。一般我们自己操作Field时,遇到 private修饰的属性就需要强制访问了,GetFiledInvoker帮我们封装了这一步,而且,只有在发生IllegalAccessException 异常时才做强制访问(用private 修饰的field字段被反射操作时,会抛出此异常),这样做的好处是对于一些无需强制访问的Field,就不再需要开启强制访问,例如用public修饰的Field.

另外这里还会去检查权限的问题,如下代码:

Reflector.canControlMemberAccessible()

就是说当你有权限的时候才能去开启强制访问,否则,你没有权限也去开启强制访问,自然也是失败的。

SetFieldInvoker和GetFieldInvoker代码几乎差不多,唯一区别是一个get,一个set,这里不再赘述。

MethodInvoker:

public class MethodInvoker implements Invoker {/*** 没有调用,还不清楚作用* */private final Class<?> type;private final Method method;/*** 参数长度是是1时,type=参数的类型* 否则,type=return type* */public MethodInvoker(Method method) {this.method = method;if (method.getParameterTypes().length == 1) {type = method.getParameterTypes()[0];} else {type = method.getReturnType();}}@Overridepublic Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {try {return method.invoke(target, args);} catch (IllegalAccessException e) {if (Reflector.canControlMemberAccessible()) {method.setAccessible(true);return method.invoke(target, args);} else {throw e;}}}@Overridepublic Class<?> getType() {return type;}
}

MethodInvoker 代码和GetFileldInvoker代码逻辑差不多,区别是MethodInvoker操作的是MethodInvoker的是Method对象,那么为什么会即提供了MethodInvoker又提供了GetFileldInvoker/SetFieldInvoker呢?我的猜测是当被操作的Bean有getter/setter时,mybatis会通过MethodInvoker来调用getter/setter完成属性的get/set,当被操作Bean的属性没有提供getter/setter时,这里就需要SetFieldInvoker和GetFieldInvoker来完成对field的get/set了,带着这个疑问我们去看一下Reflector源代码:

从setMethods/getMethods的泛型定义可以看出,这两个集合实际保存的是invoker,接着:

从266和275行可以得到两条信息:

1,setMethods/getMethods的key是field name

2,只有当setMethods中不存在该字段名对应的invoker时,才会添加,那么在什么情况下不存在呢?在该field没有getter/setter时。

也就是说,当setMethods|getMethods中没有field name对应methodInvoker时,才会调用 addSetField/addGetField,我们打开其中一个方法:

286行显示add了一个SetFieldInvoker并put到了setMethods中。

AmbiguousMethodInvoker:

public class AmbiguousMethodInvoker extends MethodInvoker {private final String exceptionMessage;public AmbiguousMethodInvoker(Method method, String exceptionMessage) {super(method);this.exceptionMessage = exceptionMessage;}@Overridepublic Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException {throw new ReflectionException(exceptionMessage);}

Ambiguous是有歧义的意思,从字面意思上来猜测,它是一种提高健壮性的设计,当getter/setter的方法签名相同,返回类型却不同时,初始化不会停止,有歧义的getter/setter也不会被丢弃,如果你不调用,相安无事,当你调用的时候,立马抛出异常告诉你,这个方法可能由歧义。

 

这篇关于Mybatis Invoker的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/390112

相关文章

将Mybatis升级为Mybatis-Plus的详细过程

《将Mybatis升级为Mybatis-Plus的详细过程》本文详细介绍了在若依管理系统(v3.8.8)中将MyBatis升级为MyBatis-Plus的过程,旨在提升开发效率,通过本文,开发者可实现... 目录说明流程增加依赖修改配置文件注释掉MyBATisConfig里面的Bean代码生成使用IDEA生

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

MyBatis 动态 SQL 优化之标签的实战与技巧(常见用法)

《MyBatis动态SQL优化之标签的实战与技巧(常见用法)》本文通过详细的示例和实际应用场景,介绍了如何有效利用这些标签来优化MyBatis配置,提升开发效率,确保SQL的高效执行和安全性,感... 目录动态SQL详解一、动态SQL的核心概念1.1 什么是动态SQL?1.2 动态SQL的优点1.3 动态S

Spring Boot结成MyBatis-Plus最全配置指南

《SpringBoot结成MyBatis-Plus最全配置指南》本文主要介绍了SpringBoot结成MyBatis-Plus最全配置指南,包括依赖引入、配置数据源、Mapper扫描、基本CRUD操... 目录前言详细操作一.创建项目并引入相关依赖二.配置数据源信息三.编写相关代码查zsRArly询数据库数

Spring Boot 整合 MyBatis 连接数据库及常见问题

《SpringBoot整合MyBatis连接数据库及常见问题》MyBatis是一个优秀的持久层框架,支持定制化SQL、存储过程以及高级映射,下面详细介绍如何在SpringBoot项目中整合My... 目录一、基本配置1. 添加依赖2. 配置数据库连接二、项目结构三、核心组件实现(示例)1. 实体类2. Ma

Mybatis从3.4.0版本到3.5.7版本的迭代方法实现

《Mybatis从3.4.0版本到3.5.7版本的迭代方法实现》本文主要介绍了Mybatis从3.4.0版本到3.5.7版本的迭代方法实现,包括主要的功能增强、不兼容的更改和修复的错误,具有一定的参考... 目录一、3.4.01、主要的功能增强2、selectCursor example3、不兼容的更改二、

mybatis-plus分页无效问题解决

《mybatis-plus分页无效问题解决》本文主要介绍了mybatis-plus分页无效问题解决,原因是配置分页插件的版本问题,旧版本和新版本的MyBatis-Plus需要不同的分页配置,感兴趣的可... 昨天在做一www.chinasem.cn个新项目使用myBATis-plus分页一直失败,后来经过多方

mybatis-plus 实现查询表名动态修改的示例代码

《mybatis-plus实现查询表名动态修改的示例代码》通过MyBatis-Plus实现表名的动态替换,根据配置或入参选择不同的表,本文主要介绍了mybatis-plus实现查询表名动态修改的示... 目录实现数据库初始化依赖包配置读取类设置 myBATis-plus 插件测试通过 mybatis-plu

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景

MyBatis-Plus中静态工具Db的多种用法及实例分析

《MyBatis-Plus中静态工具Db的多种用法及实例分析》本文将详细讲解MyBatis-Plus中静态工具Db的各种用法,并结合具体案例进行演示和说明,具有很好的参考价值,希望对大家有所帮助,如有... 目录MyBATis-Plus中静态工具Db的多种用法及实例案例背景使用静态工具Db进行数据库操作插入