一、背景
最近在工作之余,把开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. 性能优化之reflow和repaint

    本文主要介绍一下什么是reflow,repaint, 怎样避免它们造成的不良影响, 怎么通过工具查看分析它们. 一.首先对浏览器渲染引擎下网页呈现过程简要说一下: 浏览器的渲染引擎开始解析html构建 ...

  2. AvalonJS前端开发源码

    avBody = avalon.define("avBody", function (vm) { vm.Address = "";//地址 vm.BrandMo ...

  3. ES6的generator函数

    generator是什么? generator是ES6提供的一种异步编程解决方案,在语法上,可以把它理解为一个状态机,内部封装了多种状态.执行generator,会生成返回一个遍历器对象.返回的遍历器 ...

  4. 数据库操作sql

    一.把从另外一张表里查到的值插入到前表: 1. 表结构完全一样 insert into 表1 select * from 表2 2. 表结构不一样(这种情况下得指定列名) insert into 表1 ...

  5. 详解小白利用eclipse+CDT+MinGW搭建C++开发环境

    安装JDK.安装Eclipse     2.打开Eclipse 找到“help”下的“Eclipse marketplace” 如图:    3.选择相应的C插件: 因为安装过所以显示installe ...

  6. redis备份与恢复

    1.redis的备份 redis需要远程访问 添加密码进行登录,修改主配置文件添加:requirepass xxx redis-cli -h 127.0.0.1 -p 6379 -a 123456 b ...

  7. PHP Session 常用的函数

    我们在前面的文章里面讲到session的原理和最佳实践,感到意犹未尽.现在再来聊下PHP Session用到的几个相关的函数. session_start() session_start() 会创建新 ...

  8. jquery easyui+spring mnv 样式引不进,需要加载静态资源

    前台用的EasyUI,页面中引入了easyUI的js与css(引入路径正确),但是无论如何都显示不出来, 如下图: EasyUI的样式没有,看控制台:警告,找不到 21:26:25,643 WARN  ...

  9. Matlab绘图基础——散点生成三角网(TIN)

    %例一:二维三角网TIN模型的生成 X=rand(10,2)*5; dt=DelaunayTri(X(:,1),X(:,2));       %生成三角网 triplot(dt);hold on;   ...

  10. 爬虫(scrapy中调试文件)

    在项目setting同级目录下创建py文件,代码如下: from scrapy.cmdline import execute import sys import os sys.path.append( ...