前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >动态代理的实际应用

动态代理的实际应用

作者头像
crossoverJie
发布于 2022-10-27 03:44:56
发布于 2022-10-27 03:44:56
43400
代码可运行
举报
文章被收录于专栏:crossoverJiecrossoverJie
运行总次数:0
代码可运行

前言

最近在用 PythonSQLAlchemy 库时(一个类似于 HibernateORM 框架),发现它的 Events 事件还挺好用。

简单说就是当某张表的数据发生变化(曾、删、改)时会有一个事件回调,这样一些埋点之类的需求都可以实现在这里,同时和业务代码完全解耦,维护起来也很方便。

例如当订单状态发生变化需要发异步通知这样的需求也可以利用这个实现。

根据我之前使用 Mybatis 的经验,好像没怎么注意有这个功能,查阅了下发现 Hibernate 是支持的,只是我用得也少,所以也没怎么在意。

逐渐偏离主题。。。

说这些的主要原因是我打算为之前写的 cicada (轻量的 http 框架)加一个数据库操作包,也实现类似的功能。

示例

最终的使用效果如下:

第一版本还比较粗糙,但功能都具备。

第一步:需要实现一个初始化接口,该接口会在应用初始化的时候执行。


紧接着我们需要定义一个 Model

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Data 
@OriginName("user") 
@ToString 
public class User extends Model { 
 @PrimaryId 
 private Integer id ; 
 private String name ; 
 private String password ; 
 @FieldName(value = "city_id") 
 private Integer cityId ; 
 private String description ; 
} 

它所对应的表结构如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
CREATE TABLE `user` (
 
 `id` int(11) NOT NULL AUTO_INCREMENT,
 
 `name` varchar(50) DEFAULT NULL,
 
 `password` varchar(100) DEFAULT NULL,
 
 `description` varchar(100) DEFAULT NULL,
 
 `roleId` int(11) DEFAULT NULL COMMENT '角色ID',
 
 `city_id` int(11) DEFAULT NULL,
 
  PRIMARY KEY (`id`)
 
)
 

当需要查询数据时:

便可以这样访问数据库。

当需要更新数据时:

在初始化 DBHandle 时指定一个回调接口(也就是这里的 UserUpdateListener),便可以在修改数据的时候拿到本次修改的数据实体。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@Slf4j
 
public class UserUpdateListener implements DataChangeListener {
 
 @Override
 
 public void listener(Object obj) {
 
        log.info("user update data={}", obj.toString());
 
 }
 
}
 

同时我们可以在控制台看到数据修改时的回调结果:

这样就实现了文初所提到的功能,便可以实现一些数据变化后需要执行的业务逻辑。

实现

下面重点来看看这个功能的实现过程;其实通过生成 DBHandle(数据库增删改的接口)实例的 API 便可以看出些端倪。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
DBHandle handle = (DBHandle) new HandleProxy(DBHandle.class).getInstance(new UserSaveListener()); 

DBHandel 虽然是个接口,但是它并不是使用一个实现类来实现的,而是通过代理生成。

那通过代理生成比直接实例化实现类有啥好处呢?

举个例子,比如现在你想买一个新手机。

第一种方式可以直接在官方旗舰店买一个标配的手机,没有额外的东西只有一个手机。

当然你也可以在某些第三方经销商那里购买带套餐的,比如 套餐一在标配的基础上多了 保护壳、贴膜之类的附加属性。

这个经销商就类似于我们这里的代理类,他可以在原有实现的基础上新增一些东西,至于新增什么全看你自己的需要了。

而之所以叫动态代理,也是因为这个代理类是在程序运行过程中动态创建的,在编译过程中并不能确定这个类的全限定名。

下面来看看这个代理类是如何生成的:

主要利用 JDK 自带的 API 实现的,具体参数可以直接参考官方文档

总之这样便可以创建一个 DBHandler 接口的代理对象,而真正的代理过程是在 InvocationHandler#invoke() 函数中实现的:

这里的实现也是非常简单,在实现完代理对象的业务逻辑后便回调我们传入的事件接口,其中的参数便是当前的数据库 Model 实体对象。

不过需要注意的是,这个事件回调和业务线程是同一个,所以写在这里的逻辑建议都为异步(Hibernate 和 SQLAlchemy 都存在这个情况)。

总结

以上便是整个动态代理实现 ORM 监听机制的全过程,其实可以看出并没有它名称那样看起来高大上,当然本身实现也比较简单。

同时也不止这一种实现方式,例如:

  • cglib
  • javassist
  • ASM

etc..

他们的具体实现及优劣就不在本文探讨了,感兴趣的后续我会将这个功能用这几种方式实现一遍。

同时动态代理的应用也不止于此,比如:

  • RPC 中无感知的远程调用。
  • Spring 中的 AOP、拦截器等。

后续会继续完善这个 ORM 库,甚至可以独立出来作为一个小巧的数据库工具也未尝不可。

相关源码见此处:https://github.com/TogetherOS/cicada

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

本文分享自 crossoverJie 微信公众号,前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Java 动态代理,看这篇就够了
这篇文章需要用到 Java 的反射知识,如果对反射还不清楚的小伙伴,可以先移步到这里 《Java进阶-反射》。
Wizey
2018/09/29
4500
Java 动态代理,看这篇就够了
【设计模式】代理模式 ( 动态代理 )
业务场景 : 保存订单信息 , 在 Service 层处理订单保存 , 在 Dao 层将订单存储到数据库 ; 使用动态代理类加强 Service 层的功能 ;
韩曙亮
2023/03/29
3010
【设计模式】代理模式 ( 动态代理 )
Java 动态代理都不懂怎么装逼?
好几天不写文章,今天来写一篇,从之前的计划表上看到还有关于java的动态代理没写,这个技术平常用的少,也不是特别好理解,今天补上这篇,希望能讲明白,不至于像我一样迷茫好久,开始吧
香菜聊游戏
2021/07/13
1.7K0
Java 动态代理都不懂怎么装逼?
你必须会的 JDK 动态代理和 CGLIB 动态代理
我们在阅读一些 Java 框架的源码时,基本上常会看到使用动态代理机制,它可以无感的对既有代码进行方法的增强,使得代码拥有更好的拓展性。通过从静态代理、JDK 动态代理、CGLIB 动态代理来进行本文的分析。
ytao
2020/06/04
5170
你必须会的 JDK 动态代理和 CGLIB 动态代理
设计模式之代理,手动实现动态代理,揭秘原理实现
  所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的左右。
青石路
2019/03/20
5540
设计模式之代理,手动实现动态代理,揭秘原理实现
017 Java中的静态代理、JDK动态代理、cglib动态代理
一、静态代理 代理模式是常用设计模式的一种,我们在软件设计时常用的代理一般是指静态代理,也就是在代码中显式指定的代理。 静态代理由业务实现类、业务代理类两部分组成。业务实现类负责实现主要的业务方法,业务代理类负责对调用的业务方法作拦截、过滤、预处理。在需要调用业务时,不是直接通过业务实现类来调用的,而是通过业务代理类的同名方法来调用被处理过的业务方法。 静态代理的实现: 1、首先定义一个接口,说明业务逻辑。 package com.nnngu.dao; /** * 定义一个账
nnngu
2018/03/15
6710
浅析MyBatis的动态代理原理[通俗易懂]
前言 一直以来都在使用MyBatis做持久化框架,也知道当我们定义XXXMapper接口类并利用它来做CRUD操作时,Mybatis是利用了动态代理的技术帮我们生成代理类。那么动态代理内部的实现细节到底是怎么的呀?XXXMapper.java类和XXXMapper.xml到底是如何关联起来的呀?本篇文章就来详细剖析下MyBatis的动态代理的具体实现机制。
全栈程序员站长
2022/09/22
2K0
详解Java动态代理机制
Single
2018/01/04
6160
详解Java动态代理机制
Java中的静态代理和动态代理
Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式。在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。目的:为其他对象提供一种代理以控制对这个对象的访问。
花落花相惜
2021/11/23
2850
动态代理竟然如此简单!
动态代理在 Java 中有着广泛的应用,比如 AOP 的实现原理、RPC远程调用、Java 注解对象获取、日志框架、全局性异常处理、事务处理等。
cxuan
2021/01/06
3680
动态代理竟然如此简单!
Java代理1 代理和动态代理的基础与使用
预计分两篇写,第一篇是基础和一般用法,第二篇详细写下动态代理。本篇基础主要来自《Think in java》阅读笔记。
WindCoder
2018/09/19
3320
Java代理和动态代理机制分析和应用
本博文中项目代码已开源下载地址:GitHub Java代理和动态代理机制分析和应用 概述 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种。 代理模式一般涉及到的角色有4种 主题接口:定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法; 真实主题:真正实现业务逻辑的类; 代理类:用来代理和封装真实主题; 客户端:使
CrazyCodeBoy
2018/05/07
7140
Java代理和动态代理机制分析和应用
细说java系统之动态代理
在深入学习动态代理之前,需要先掌握代理模式。只有深刻理解了代理模式的应用,才能充分理解Java动态代理带来的便利。 在生活中存在许多使用“代理模式”的场景,比如:村里的张三今年已经30岁了,但是还没结婚,可把他老妈给愁坏了,于是就拜托村东头的王媒婆给儿子找个媳妇。 在这里,要娶媳妇的人是张三,但是他不能直接跑到女方家把人家闺女直接带回来,需要中间人王媒婆上门说媒,在这里王媒婆就是一个代理。 另外,我们上大学的时候都知道,学校的机房都是通过一个代理服务器上网的,因为只有一个外网IP,不允许每一台局域网的机器都直连外网。 再者,我们通常为了保护应用程序不受外网攻击,通常将nginx部署在应用前端,作为反向代理服务器。 总之,我们总是会出于某些目的,或者因为某些限制而不得不使用代理模式。
编程随笔
2019/09/11
4210
细说java系统之动态代理
Java | 静态代理与动态代理真的超简单
静态代理: 由我们开发者自己手动创建或者在程序运行前就已经存在的代理类,静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
Petterp
2022/02/09
4580
Mybatis 初探,动态代理
在项目中经常使用Mybatis框架作用DAO层,但是你真的对Mybatis的原理清楚吗?带着这个疑惑我们来实现一个简单的动态代理,本次了解的是接口实现动态代理,还有基于类的Mybatis的实现不在本次讨论范围之内
tanoak
2018/06/10
3630
Spring高手之路17——动态代理的艺术与实践
动态代理是一种强大的设计模式,它允许开发者在运行时创建代理对象,用于拦截对真实对象的方法调用。这种技术在实现面向切面编程(AOP)、事务管理、权限控制等功能时特别有用,因为它可以在不修改原有代码结构的前提下,为程序动态地注入额外的逻辑。
砖业洋__
2024/04/13
4480
Spring高手之路17——动态代理的艺术与实践
动态代理机制
代理模式是指,为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户类和目标对象之间起到中介的作用。 换句话说,使用代理对象,是为了在不修改目标对象的基础上,增强主业务逻辑。 客户类真正想要访问的对象是目标对象,但客户类真正可以访问的对象是代理对象。客户类对目标对象的访问是通过访问代理对象来实现的。代理类与目标类要实现同一个接口。 例如:有A,B,C三个类,A原来可以调用C类的方法,现在因为某种原因C类不允许A类调用其方法,但B类可以调用C类的方法,A类通过B类调用C类的方法。这里B是C的代理,A通过代理B访问C。 原来的访问关系:
技术交流
2022/11/18
2380
动态代理机制
动态代理
代理模式是指:为其他对象提供一种代理以控制对某个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,此时可以引入代理对象作为该情况下客户端和目标对象之间的中介。
benym
2023/02/14
4010
大白话说Java动态代理:一个面包店的动态代理帝国
代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位。代理模式从类型上来说,可以分为静态代理和动态代理两种类型。 在开始之前,我们先假设这样一个场景:有一个蛋糕店,它们卖的蛋糕都是用蛋糕机做的,而且不同种类的蛋糕由不同的蛋糕机来做,这样就有:水果蛋糕机、巧克力蛋糕机等。它们卖的面包片也是用面包机做的,同样不同种类的面包片也是由不同的面包机来做,这样就有:葡萄干面包机、红豆面包机等。这个场景用 Java 语言描述就是下面这样: //做蛋
陈树义
2018/04/13
6930
大白话说Java动态代理:一个面包店的动态代理帝国
JDK动态代理和CGLIB动态代理
Java动态代理是一种在运行时创建代理对象的技术,它允许开发者在不修改目标类代码的情况下,通过代理类对目标类的实例方法进行增强或拦截。动态代理的核心价值在于能够在程序运行阶段动态地生成一个实现了预定义接口的新类,这个新类就是所谓的“代理类”。
程序猿川子
2025/02/27
1360
JDK动态代理和CGLIB动态代理
推荐阅读
相关推荐
Java 动态代理,看这篇就够了
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文