一、背景
最近在工作之余,把开mybatis的源码看了下,决定自己手写个简单版的。实现核心的功能即可。写完之后,执行了一下,正巧在mybatis对Mapper接口的动态代理这个核心代码这边发现一个问题。正好再回头看了下jdk的动态代理发现问题所在。

二、问题
问题所在,当我用SqlSession.getMapper() 方法来获取Mapper的代理类的时候,发现这个代理对象所展示的toString()是个null。如下图

而debug了一下mybatis的源码发,发现是有值,并且的确是new 的MapperProxy类型的对象

三、回头看jdk动态代理
当我在排查问题的时候,无意中发现,在执行(T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);方法时,竟然会抛出 mapperProxy类的invoke方法中的异常,但是这个时候程序还没有走到任何代理的方法。
回头找了下之前学着写的动态代理的例子,并在invoke方法里面输出了method。如下:

启动main方法,发现打印的内容:

这时候才发现,在实例化代理类的时候,会调用一次invoke()方法,并且此时调用方法的method参数是Object.toString() 。看到这发现了两点

  1. invoke方法在实例化代理的时候会调用一次,如果这个方法有对全局的公共变量做修改的话,会存在隐患的问题
  2. 代理类的toString 最后出来的类的名称就是调用这个方法得到的。将代码中result输出就是对应的代理类。

四、发现并解决问题
回到自己的手写的mybatis源码中,自然就定位到了如下这个地方:

对比一下mybatis的源码

正是红框中的代码,自己手写的时候认为代理的方法的声明类都是定义的mapper接口,这边的判断其实没有必要,也走不到。然而从第三点中可以知道,在new 代理类的时候传入的Method为toString方法正好进了这个分支,并且调用了当前MapperProxy实例的toString方法,返回了代理类的名称,正式之前所缺失的。把这段代码加上就OK了

从Mybatis源码理解jdk动态代理默认调用invoke方法的更多相关文章

  1. mybatis源码阅读(动态代理)

    这一篇文章主要是记录Mybatis的动态代理学习成果,如果对源码感兴趣,可以看一下上篇文章  https://www.cnblogs.com/ChoviWu/p/10118051.html 阅读本篇的 ...

  2. mybatis源码学习: 动态代理的应用(慢慢改)

    动态代理概述 在学spring的时候知道使用动态代理实现aop,入门的列子:需要计算所有方法的调用时间.可以每个方法开始和结束都获取当前时间咋办呢.类似这样: long current=system. ...

  3. Mybatis源码解析(三) —— Mapper代理类的生成

    Mybatis源码解析(三) -- Mapper代理类的生成   在本系列第一篇文章已经讲述过在Mybatis-Spring项目中,是通过 MapperFactoryBean 的 getObject( ...

  4. Mybatis-简单基于源码了解获取动态代理对象

    这是我们要测试的代码 OderDao就是我们要需要获取的对象. 首先我们根据传入的参数,进入SqlSessionFactoryBuilder 中的对应的build 方法,第一步创键XMLConfigB ...

  5. 举例理解JDK动态代理

    JDK动态代理 说到java自带的动态代理api,肯定离不开反射.JDK的Proxy类实现动态代理最核心的方法: public static Object newProxyInstance(Class ...

  6. MyBatis之反射技术+JDK动态代理+cglib代理

    一.反射 引用百度百科说明: JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功 ...

  7. Mybatis源码解析5—— 接口代理

    本篇文章,可乐将为大家介绍通过接口代理的方式去执行SQL操作.话不多说,直接上图: 其实无论哪种方式,我们最终是需要找到对应的 SQL 语句,接口代理的方式就是通过 [包名.方法名] 的方式,去找到 ...

  8. JDK动态代理

    一.基本概念 1.什么是代理? 在阐述JDK动态代理之前,我们很有必要先来弄明白代理的概念.代理这个词本身并不是计算机专用术语,它是生活中一个常用的概念.这里引用维基百科上的一句话对代理进行定义: A ...

  9. 深入浅出JDK动态代理(一)

    1.何为代理 代理,即代替主角完成一些额外的事情.例如,明星都有经纪人,明星参演电影之前,经纪人作为明星的代理人和出资方洽谈片酬.排期等,而真正参与拍戏的还是明星本人,明星拍完戏后,由经纪人代理明星去 ...

随机推荐

  1. VirboxLM许可管理平台,一站式软件保护解决方案

    安全,易用,灵活 轻松解决开发者软件版权保护难题 Virbox LM为企业提供安全易用的软件保护管理平台,实现高安全强度的软件防护,防止盗版及逆向工程.实现便捷.安全的软件授权,包括创建灵活的许可模式 ...

  2. Java设计模式(二)抽象工厂模式

    一.场景描述 接<Java设计模式(一)工厂模式>https://www.cnblogs.com/mahongbiao/p/8618970.html 工厂模式有一缺点,就是破坏了类的封闭性 ...

  3. 以太坊go-ethereum签名部分源码解析

    以太坊go-ethereum签名部分源码解析 golang标准库里的crypto/ecdsa椭圆曲线加密算法所提供的函数有: ecdsa.PublicKey结构体通过持有一个elliptic,Curv ...

  4. 记录Window系统下myeclipes连接linux下mysql所出现的一个bug

    记录myeclipes远程连接mysql所出现的一个bug 今天在玩框架hibernate时,出现一个非常费解的bug,话不多说,先看bug Access denied for user 'root' ...

  5. eclipse打包

  6. Android实用代码七段(二)

    正文 一.获取应用程序下所有Activity public static ArrayList<String> getActivities(Context ctx) {       Arra ...

  7. Android游戏开发之旅 View类详解

    Android游戏开发之旅 View类详解 自定义 View的常用方法: onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) ...

  8. Struts2学习笔记五 拦截器

    拦截器,在AOP中用于在某个方法或字段被访问之前,进行拦截,然后在之前或之后加入某些操作.拦截是AOP的一种实现策略. Struts2中,拦截器是动态拦截Action调用的对象.它提供了一种机制可以使 ...

  9. 计算1-1/3+1/5-1/7+···的前n项和

    这图1为书里的教材,图二为自己打的程序 (1)二者相比,自己写的代码显得更短,听说代码写的越精简越好,但是自己的较难分析,他人看来可能会较难理解一点:(自己在第一次运行时将for()中的第二个表达式写 ...

  10. 极其简单的帮你理解ORM中的关联关系

    ORM对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转 ...