热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

mybatis中的扩展实现源码解析

这篇文章主要介给大家绍了关于mybatis中扩展实现的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

最近项目中需要用到mybatis的扩展,就深入看了下mybatis的实现,对其灵活性和扩展性的设计思想还是非常佩服的

首先说一下mybatis的拦截器使用方法:继承其Intercepter接口,实现org.apache.ibatis.plugin.Interceptor#intercept方法,在其中或者对其要执行的方法进行拦截,或者对返回值进行解析

同时基于org.apache.ibatis.plugin.Interceptsorg.apache.ibatis.plugin.Signature这两个注解来决定,对哪些执行器的哪些方法进行拦截

先看下拦截器的核心接口

public interface Interceptor {
 
 Object intercept(Invocation invocation) throws Throwable;
 
 Object plugin(Object target);
 
 void setProperties(Properties properties);
 
}

其中intercept方法是核心方法,拦截器的实现,plugin方法是用于配置哪些对哪些执行器进行拦截

继续看源码,可以看到mybatis的拦截是使用了jdk的动态代理实现的,本质上是一种代理机制

public class Plugin implements InvocationHandler {
 
 private final Object target;
 private final Interceptor interceptor;
 private final Map, Set> signatureMap;
 
 private Plugin(Object target, Interceptor interceptor, Map, Set> signatureMap) {
 this.target = target;
 this.interceptor = interceptor;
 this.signatureMap = signatureMap;
 }
 
 public static Object wrap(Object target, Interceptor interceptor) {
 Map, Set> signatureMap = getSignatureMap(interceptor);
 Class<&#63;> type = target.getClass();
 Class<&#63;>[] interfaces = getAllInterfaces(type, signatureMap);
 if (interfaces.length > 0) {
  return Proxy.newProxyInstance(
   type.getClassLoader(),
   interfaces,
   new Plugin(target, interceptor, signatureMap));
 }
 return target;
 }
 
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
 try {
  Set methods = signatureMap.get(method.getDeclaringClass());
  if (methods != null && methods.contains(method)) {
  return interceptor.intercept(new Invocation(target, method, args));
  }
  return method.invoke(target, args);
 } catch (Exception e) {
  throw ExceptionUtil.unwrapThrowable(e);
 }
 }
 
 ......
}

mybatis的这个Plugin就是代理类,这个代理类是在org.apache.ibatis.plugin.Interceptor#plugin方法中初始化的(调用org.apache.ibatis.plugin.Plugin#wrap),一个Plugin包含一个Intercepter,以及该Intercepter相关的注解配置信息,当对拦截对象的对应方法进行执行的时候,都会根据这些注解配置来判断是否需要执行该代理拦截(org.apache.ibatis.plugin.Plugin#invoke

再看下plugin是如何被加载的:

public class InterceptorChain {
 
 private final List interceptors = new ArrayList();
 
 public Object pluginAll(Object target) {
 for (Interceptor interceptor : interceptors) {
  target = interceptor.plugin(target);
 }
 return target;
 }
 
 public void addInterceptor(Interceptor interceptor) {
 interceptors.add(interceptor);
 }
 
 public List getInterceptors() {
 return Collections.unmodifiableList(interceptors);
 }
 
}

org.apache.ibatis.plugin.Interceptor#plugin是在org.apache.ibatis.plugin.InterceptorChain#pluginAll方法中调用的,我们可以看到,如果一个应用中注册了多个拦截器,那么实际上是会进行一个for循环的加载,由于上面说到了,加载一次,本质上是对mybatis的执行期进行一次代理包装,那么加载多次的话,就会代理包装多次,实际上就是一种多重代理了,这样就保证了每次调用都会按照代理顺序进行调用和返回的处理

可以看到,在做这些mybatis执行器初始化的时候,都会进行拦截器链的加载

至此,mybatis基于jdk动态代理的扩展实现方法就了解清楚了,其灵活性在于,它抽象了执行器的概念,并且拦截器的拦截方法也是固定的,我们可以对不同执行器的不同方法进行拦截,而对这些扩展点进行扩展却不用写多个方法实现多个方法,只需要实现一个接口就可以搞定了!

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


推荐阅读
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了在Win10上安装WinPythonHadoop的详细步骤,包括安装Python环境、安装JDK8、安装pyspark、安装Hadoop和Spark、设置环境变量、下载winutils.exe等。同时提醒注意Hadoop版本与pyspark版本的一致性,并建议重启电脑以确保安装成功。 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
  • mac php错误日志配置方法及错误级别修改
    本文介绍了在mac环境下配置php错误日志的方法,包括修改php.ini文件和httpd.conf文件的操作步骤。同时还介绍了如何修改错误级别,以及相应的错误级别参考链接。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 如何提高PHP编程技能及推荐高级教程
    本文介绍了如何提高PHP编程技能的方法,推荐了一些高级教程。学习任何一种编程语言都需要长期的坚持和不懈的努力,本文提醒读者要有足够的耐心和时间投入。通过实践操作学习,可以更好地理解和掌握PHP语言的特异性,特别是单引号和双引号的用法。同时,本文也指出了只走马观花看整体而不深入学习的学习方式无法真正掌握这门语言,建议读者要从整体来考虑局部,培养大局观。最后,本文提醒读者完成一个像模像样的网站需要付出更多的努力和实践。 ... [详细]
  • 本文介绍了使用Spark实现低配版高斯朴素贝叶斯模型的原因和原理。随着数据量的增大,单机上运行高斯朴素贝叶斯模型会变得很慢,因此考虑使用Spark来加速运行。然而,Spark的MLlib并没有实现高斯朴素贝叶斯模型,因此需要自己动手实现。文章还介绍了朴素贝叶斯的原理和公式,并对具有多个特征和类别的模型进行了讨论。最后,作者总结了实现低配版高斯朴素贝叶斯模型的步骤。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • 大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记
    本文介绍了大数据Hadoop生态(20)MapReduce框架原理OutputFormat的开发笔记,包括outputFormat接口实现类、自定义outputFormat步骤和案例。案例中将包含nty的日志输出到nty.log文件,其他日志输出到other.log文件。同时提供了一些相关网址供参考。 ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • Java如何导入和导出Excel文件的方法和步骤详解
    本文详细介绍了在SpringBoot中使用Java导入和导出Excel文件的方法和步骤,包括添加操作Excel的依赖、自定义注解等。文章还提供了示例代码,并将代码上传至GitHub供访问。 ... [详细]
  • Apache Shiro 身份验证绕过漏洞 (CVE202011989) 详细解析及防范措施
    本文详细解析了Apache Shiro 身份验证绕过漏洞 (CVE202011989) 的原理和影响,并提供了相应的防范措施。Apache Shiro 是一个强大且易用的Java安全框架,常用于执行身份验证、授权、密码和会话管理。在Apache Shiro 1.5.3之前的版本中,与Spring控制器一起使用时,存在特制请求可能导致身份验证绕过的漏洞。本文还介绍了该漏洞的具体细节,并给出了防范该漏洞的建议措施。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
author-avatar
傅雪莱_
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有