首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JDK动态代理一定要有代理对象吗?请结合Mybatis回答

JDK动态代理一定要有代理对象吗?请结合Mybatis回答

作者头像
微笑的小小刀
发布于 2020-06-19 03:06:08
发布于 2020-06-19 03:06:08
43500
代码可运行
举报
文章被收录于专栏:java技术大本营java技术大本营
运行总次数:0
代码可运行

动态代理

有一段时间没有写文章了, 主要是回想起这两年多的时间,多多少少,每个知识点差不多都有写到了, 一时也想不起什么新鲜的知识分享给大家. 今天写动态代理,主要是在看Mybatis源码时,发现真的是把动态代理用的是太6 了, 感叹之余,有一些心得,和大家分享一下.

我所理解的动态代理

其实网上对动态代理的解释有很多了,我就不赘述那些概念了, 于小刀看来, 目的只有一个,那就是可以自定义逻辑,可以添加逻辑. 在本文中,我想写的是可以自定义逻辑, 在此之前,我们先看一下通常的动态代理的代码

动态代理代码

源码地址:

https://github.com/xiaodaojava/sunshine/tree/master/sunshine-base/src/main/java/red/lixiang/tools/demo/proxy/dynamic

接口

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author lixiang
 * @date 2020/6/16
 **/
public interface Greet {
    /**
     * 加油的接口定义
     */
    public void cheer();
}

实现类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author lixiang
 * @date 2020/6/16
 **/
public class GreetImpl implements Greet{
    
    @Override
    public void cheer() {
        System.out.println("加油, 为了美好的明天!");
    }
}

代理类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author lixiang
 * @date 2020/6/16
 **/
public class GreetProxy implements InvocationHandler {
    
    /** 被代理的对象,真正的逻辑,还是要请求这个 */
    private final Greet greet;

    public GreetProxy(Greet greet) {
        this.greet = greet;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("在真正调用之前");
        greet.cheer();
        System.out.println("在真正调用之后");
        return null;
    }
}

Main函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author lixiang
 * @date 2020/6/16
 **/
public class ProxyMain {
    public static void main(String[] args) {
        // 真正的对象
        Greet greet = new GreetImpl();
        // 代理对象
        InvocationHandler handler = new GreetProxy(greet);
        // 使用的jdk代理生成代理类
        Greet proxy = (Greet)Proxy.newProxyInstance(ProxyMain.class.getClassLoader(), new Class[]{Greet.class}, handler);
        proxy.cheer();
    }
}

我们在运行的时候打个断点,可以看到:

如上图所示,我们虽然把jdk生成的代理对象强转成了Greet,但实际上是Proxy类型,运行结果如下图所示:

进入正文

上面这些代码, 是平常的增加逻辑的用法,但,今天小刀想和大家聊的是: 自定义逻辑.先看代码 接口不变,

代理类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author lixiang
 * @date 2020/6/16
 **/
public class GreetCustomProxy implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("所谓自定义就是,这个代理类里面并没有Greet的真正实现类");
        System.out.println("全都是加强的逻辑");
        return null;
    }
}

main函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * @author lixiang
 * @date 2020/6/16
 **/
public class ProxyCustomMain {
    public static void main(String[] args) {
        InvocationHandler handler = new GreetCustomProxy();
        Greet proxy = (Greet) Proxy.newProxyInstance(ProxyMain.class.getClassLoader(), new Class[]{Greet.class}, handler);
        proxy.cheer();
    }
}

运行结果如下:

全文的重点

是可以正常运行的, 这里会打破大家一个思维定式,就是代理类里面并不一定需要真正的处理对象. 可能全部都是自定义的逻辑.

源码中的应用

主要是mybatis , 我们想一下, 在写sql时, 我们经常DAO里面都是接口和定义的方法, 然后mapper的xml里面写SQL, 那么这两者是怎么对应起来的呢? 今天先不细讲, 只是看看动态代理的使用,要出场的是MapperProxy MapperProxyFactory:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
protected T newInstance(MapperProxy<T> mapperProxy) {
    return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
  }

我们可以看到,传入的InvocationHandler实际上是mapperProxy

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    try {
  // 处理Object相关的方法
      if (Object.class.equals(method.getDeclaringClass())) {
        return method.invoke(this, args);
      } else {
  // 我们的重点关注对象
        return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
      }
    } catch (Throwable t) {
      throw ExceptionUtil.unwrapThrowable(t);
    }
  }

cachedInvoker 通过源码,我们可以跟踪到的代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 如果是接口中的default方法,则直接执行
if (m.isDefault()) {
          try {
            if (privateLookupInMethod == null) {
              return new DefaultMethodInvoker(getMethodHandleJava8(method));
            } else {
              return new DefaultMethodInvoker(getMethodHandleJava9(method));
            }
          } catch (IllegalAccessException | InstantiationException | InvocationTargetException
              | NoSuchMethodException e) {
            throw new RuntimeException(e);
          }
        } else {
  // 其他的,就是sql语句之类的
          return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
        }

最终我们可以看到:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Override
    public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
      return mapperMethod.execute(sqlSession, args);
    }

然后使用sqlSession去执行Sql

总结

如上mybatis中对动态代理的使用,并没有实现类,真是在invoke方法中,直接调用了sqlSession去执行SQL , 刚开始看到这块时, 不是很好理解 , 要破开思维, 为什么动态代理一定要有代理对象呢? 我们也完全可以自己模拟逻辑!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java技术大本营 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
[ORM] MyBatis 中是如何运用的代理模式的?
本文主要介绍设计模式之代理模式,并分析代理模式在 Mybatis 中是如何使用的?
架构探险之道
2020/05/29
9980
[ORM] MyBatis 中是如何运用的代理模式的?
10分钟带你彻底搞懂动态代理机制
在面向对象的世界中,对象与对象之间的相互协作构成了系统的运行状态。通常,我们可以在一个对象中直接引用另一个对象来获取想要的功能,但有时候事情并没有那么简单。我们来看一段简单的代码示例:
写bug的高哈哈
2025/02/02
1220
10分钟带你彻底搞懂动态代理机制
从 Spring 集成 MyBatis 到浅析 Java 动态代理
因为 MyBatis 的易上手性和可控性,使得它成为了 ORM框架中的首选。近日新起了一个项目,所以重新搭建了一下 Spring-mybatis, 下面是搭建笔记和从 Spring-mybatis源码分析其如何使用 Java动态代理,希望对大家有帮助。
Java技术江湖
2019/09/24
4840
从 Spring 集成 MyBatis 到浅析 Java 动态代理
从 Spring 集成 MyBatis 到浅析 Java 动态代理
因为 MyBatis 的易上手性和可控性,使得它成为了 ORM框架中的首选。近日新起了一个项目,所以重新搭建了一下 Spring-mybatis, 下面是搭建笔记和从 Spring-mybatis源码分析其如何使用 Java动态代理,希望对大家有帮助。
Bug开发工程师
2019/06/03
5510
MyBatis的动态代理实现细节
一直以来都在使用MyBatis做持久化框架,也知道当我们定义XXXMapper接口类并利用它来做CRUD操作时,Mybatis是利用了动态代理的技术帮我们生成代理类。那么动态代理内部的实现细节到底是怎么的呀?XXXMapper.java类和XXXMapper.xml到底是如何关联起来的呀?本篇文章就来详细剖析下MyBatis的动态代理的具体实现机制。
二哥聊运营工具
2021/12/17
9720
MyBatis的动态代理实现细节
MyBatis源码解读(3)——MapperMethod
在前面两篇的MyBatis源码解读中,我们一路跟踪到了MapperProxy,知道了尽管是使用了动态代理技术使得我们能直接使用接口方法。为巩固加深动态代理,我们不妨再来回忆一遍何为动态代理。 我相信在初学MyBatis的时候几乎每个人都会发出一个疑问,为什么明明是XXXDao接口,我没有用任何代码实现这个接口,但却能直接使用这个接口的方法。现在清楚了,动态代理。我们来写一个demo小程序来看看。 首先是一个Test.java的接口,只有一个say方法。 1 package day_16_proxy; 2
用户1148394
2018/01/09
6540
浅析MyBatis的动态代理原理[通俗易懂]
前言 一直以来都在使用MyBatis做持久化框架,也知道当我们定义XXXMapper接口类并利用它来做CRUD操作时,Mybatis是利用了动态代理的技术帮我们生成代理类。那么动态代理内部的实现细节到底是怎么的呀?XXXMapper.java类和XXXMapper.xml到底是如何关联起来的呀?本篇文章就来详细剖析下MyBatis的动态代理的具体实现机制。
全栈程序员站长
2022/09/22
2.1K0
设计模式学习笔记(七)代理模式以及动态代理的实现
代理模式(Proxy Design Pattern)是为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象。被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象。
归思君
2023/10/16
2540
设计模式学习笔记(七)代理模式以及动态代理的实现
JDK动态代理
这里是最简单的Java接口和实现类的关系,此时可以开始动态代理了,一般会分为两个步骤:第一是建立代理对象和真实服务对象的代理和被代理关系,第二步是实现代理对象具体方法的逻辑。
itlemon
2020/04/03
5530
JDK动态代理的底层实现原理
JDK动态代理的底层实现原理      动态代理是许多框架底层实现的基础,比如Spirng的AOP等,其实弄清楚了动态代理的实现原理,它就没那么神奇了,下面就来通过案例和分析JDK底层源码来揭秘她的神秘面纱,让她一丝不挂地呈现在我们面前,邪恶了。。。 代理模式定义 存在一个代理对象,并且这个代理对象持有真实对象的引用,以实现对真实对象的访问控制。 举个例子,现在公司一般都有VPN,使我们在家也能访问到公司的内网(比如连接公司的数据库等),实现居家办公。这里VPN相当于一个代理,而公司内网相当于被代理对象,也
汤高
2018/03/28
2.2K0
JDK动态代理的底层实现原理
MyBatis的通俗理解:SqlSession.getMapper()源码分析
直接看官方文档:https://mybatis.org/mybatis-3/zh/index.html。
全栈程序员站长
2022/07/02
5620
JDK动态代理
   代理是一种软件设计模式,这种设计模式不直接访问被代理对象,而访问被代理对象的方法,详尽的解释可参考《java设计模式之禅》,里面的解释还是很通俗的。给个《java设计模式之禅》下载地址:https://pan.baidu.com/s/1GdFmZSx67HjKl_OhkwjqNg
六个核弹
2022/12/23
1660
Mybatis源码学习(二)Mapper动态代理
上一篇分析了SqlSessionFactoryBuilder是如何解析mapper的,并且mapper的核心在于会将所有的mapper接口注册到MapperRegistry中(key-mapper接口Class类,value-mapper的代理工厂)。
虞大大
2020/09/01
4410
jdk动态代理和retrofit
1.静态代理 比如说本人要买华为手机,可以自己买,也可以让别人帮着买 public interface Buyer { void buy(); } public class Me implements Buyer { @Override public void buy() { System.out.println("I want to buy HUAWEI"); } } 现在本人比较忙,所以决定让姐姐帮我代购(当然,也可以是其他人) public class
提莫队长
2020/06/02
3290
jdk动态代理和cglib动态代理详解
如上图,代理模式可分为动态代理和静态代理,我们比较常用的有动态代理中的jdk动态代理和Cglib代理,像spring框架、hibernate框架中都采用了JDK动态代理,下面将结合代码阐述两种代理模式的使用与区别。
全栈程序员站长
2022/08/29
7340
jdk动态代理和cglib动态代理详解
你做过代理吗?
这是一条优雅的分割线===========================splitter
简单的程序员
2021/03/14
3110
你做过代理吗?
Mybatis源码解析(八):Mapper代理原理
Java微观世界
2025/01/21
1360
Mybatis源码解析(八):Mapper代理原理
代理模式之jdk动态代理
有一个方法是invoke (object proxy , Method method object [ ] args );
用户2141593
2019/02/20
4420
MyBatis是如何让我们通过接口就能调用到SQL的
简化版如下: https://blog.csdn.net/sinat_25991865/article/details/89891581
code-x
2022/06/21
6130
Mybatis深入源码分析之Mapper与接口绑定原理源码分析
紧接上篇文章:Mybatis深入源码分析之SqlSessionFactoryBuilder源码分析,这里再来分析下,Mapper与接口绑定原理。
须臾之余
2019/07/30
2K0
Mybatis深入源码分析之Mapper与接口绑定原理源码分析
推荐阅读
相关推荐
[ORM] MyBatis 中是如何运用的代理模式的?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档