动态代理模式详解

article/2025/10/2 7:33:30

目录

(一)什么是动态代理模式

(二)动态代理模式入门案例

1.完成一个账户转账的功能

2. v1.0版本为转账添加一个事务

3.v2.0将事务从业务层和从持久层剥离

4.v3.0将事务使用动态代理完成

5.v3.0通过cglib实现代理模式



(一)什么是动态代理模式

动态代理是java的一种设计模式。它的特征就是委托类和代理类具有相同的接口,代理类是在委托类的代码基础上添加了其他功能,比如消息预处理、消息过滤和事后处理消息等。但是实际上业务逻辑还是有委托类去完成的,简单来说,调用委托类的时候是通过代理对象来实现的。

代理类是在程序运行的时候 创建的所以被称为动态代理。动态代理相对于静态代理更加灵活,能够根据java代码指示动态生成

(二)动态代理模式入门案例

1.完成一个账户转账的功能

CREATE TABLE `account` (`id` int(11) NOT NULL AUTO_INCREMENT,`usernumber` varchar(255) NOT NULL,`money` double NOT NULL,`password` varchar(255) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

(1)创建实体类

(2)创建DAO层

创建接口:

实现类:

public class AccountDaoImpl implements AccountDao {QueryRunner qr = new QueryRunner();//获取连接Connection conn = JDBCUtils.getConnection();@Overridepublic Account getAccountByNo(String usernumber) throws SQLException {return qr.query(conn,"select * from account where usernumber = ?",new BeanHandler<>(Account.class),usernumber);}@Overridepublic int editAccout(Account account) throws SQLException{return qr.update(conn,"update account set usernumber = ? , password = ? , money = ? where id = ?",account.getUsernumber(),account.getPassword(),account.getMoney(),account.getId());}@Overridepublic int addAccount(Account account) throws SQLException {return qr.update(conn,"insert into account (usernumber,password,money) values(?,?,?)",account.getUsernumber(),account.getPassword(),account.getMoney());}@Overridepublic int delAccount(int id) throws SQLException{return qr.update(conn,"delete from account where id = ?",id);}
}

 (3)创建业务层

实现类:

public class AccountServiceImpl implements AccountService {AccountDao accountDao = new AccountDaoImpl();@Overridepublic boolean transfer(String userNo1, String userNo2, double money) {try {//查询账户一的具体内容Account accout1 = accountDao.getAccountByNo(userNo1);//查询账户二的内容Account account2 = accountDao.getAccountByNo(userNo2);//对标账户一余额是否够if(accout1.getMoney() > money){//转户一转账accout1.setMoney(accout1.getMoney() - money);//转户二加钱account2.setMoney(account2.getMoney() + money);//转账accountDao.editAccout(accout1);accountDao.editAccout(account2);//完成return true;}else {System.out.println("账户"+accout1.getUsernumber()+"余额不足");return false;}}catch (Exception e){System.out.println("转账失败");System.out.println(e.getMessage());return false;}}
}

 (4)创建测试类

结果:

 

如果修改下代码:在业务层手动添加异常

结果:

数据库:

添加事务

2. v1.0版本为转账添加一个事务

修改持久层代码:

修改业务层代码:

在转账的方法中添加事务:

测试:

结果:

数据库:

问题:每次在业务层添加事务都需要我们程序员手动的添加,不太符合业务分层。出现层次混乱问题。

3.v2.0将事务从业务层和从持久层剥离

创建一个事务管理的工具类

public class TxManage {//获取当前线程进程的容器public static ThreadLocal<Connection> TL = new ThreadLocal<Connection>();//获取连接的方法public static Connection getConn(){//创建一个连接的变量Connection conn = TL.get();//判断该连接是否在线程容器中存在if(conn == null){//创建一个连接conn = JDBCUtils.getConnection();//将该连接放入到线程容器中TL.set(conn);}//返回连接return conn;}//事务开启的方法public static void begin(){try {getConn().setAutoCommit(false);}catch (Exception e){e.printStackTrace();}}//事务提交的方法public static void commit(){try {getConn().commit();}catch (Exception e){e.printStackTrace();}}//事务回滚的方法public static void rollback(){try {getConn().rollback();}catch (Exception e){e.printStackTrace();}}//关闭连接的方法public static void close(){//判断线程容器中连接是否为空if(TL.get() != null){try {TL.get().close();} catch (SQLException e) {e.printStackTrace();}finally {//删除线程容器中的对象TL.remove();}}}
}

改造持久层:

修改业务层:

public class AccountServiceImpl implements AccountService {//手动创建持久层AccountDao accountDao = new AccountDaoImpl();@Overridepublic boolean transfer(String userNo1, String userNo2, double money)  {try {//打开事务TxManage.begin();//查询账户一的具体内容Account accout1 = accountDao.getAccountByNo(userNo1);//查询账户二的内容Account account2 = accountDao.getAccountByNo(userNo2);//对标账户一余额是否够if(accout1.getMoney() > money){//转户一转账accout1.setMoney(accout1.getMoney() - money);//转户二加钱account2.setMoney(account2.getMoney() + money);//转账accountDao.editAccout(accout1);//手动添加错误int i = 1 / 0 ;accountDao.editAccout(account2);//提交事务TxManage.commit();//完成return true;}else {System.out.println("账户"+accout1.getUsernumber()+"余额不足");return false;}}catch (Exception e){System.out.println("转账失败");System.out.println(e.getMessage());//回顾事务TxManage.rollback();return false;}}

测试:
 

数据库:
 

代码问题:事务相对的操作在业务层手动实现的,如果我们创建一个别的功能,要添加事务,必须手动添加事务。

4.v3.0将事务使用动态代理完成

将事务在业务逻辑中剥离,使用动态代理创建。

新建一个动态代理实现的类:

//创建的动态代理类
public class DynamicProxy implements InvocationHandler {//创建一个代表委托类的属性private Object object;//创建一个构造方法,要求在创建代理类的时候,将委托类添加进来public DynamicProxy(Object object) {this.object = object;}//生成代理类的方法public Object createProxy(){//生成代理类的方法Object proxy =  Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),this);//返回代理类return proxy;}//代理类方法执行@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object o = null;try {//开启事务o = method.invoke(object,args); TxManage.begin();//执行委托类原来的方法//提交事务TxManage.commit();}catch (Exception e){//回滚事务TxManage.rollback();}finally {//关闭连接TxManage.close();}return o;}
}

 

修改持久层代码:

接口中异常处理去掉:

修改业务层:

public class AccountServiceImpl implements AccountService {//手动创建持久层AccountDao accountDao = new AccountDaoImpl();@Overridepublic boolean transfer(String userNo1, String userNo2, double money) {//查询账户一的具体内容Account accout1 = accountDao.getAccountByNo(userNo1);//查询账户二的内容Account account2 = accountDao.getAccountByNo(userNo2);//对标账户一余额是否够if (accout1.getMoney() > money) {//转户一转账accout1.setMoney(accout1.getMoney() - money);//转户二加钱account2.setMoney(account2.getMoney() + money);//转账accountDao.editAccout(accout1);//手动添加错误int i = 1 / 0;accountDao.editAccout(account2);//完成return true;}else{return false;}}

测试:

结果:

如果在转账过程中添加异常:

结果:

动态代理的特点:

是java自带的功能,使用动态代理的时候必须有接口

如果没有接口,还需要使用代理,怎样处理?

5.v3.0通过cglib实现代理模式

cglib是通过继承来实现代理

  1. 导入cglib依赖

2.创建cglib代理类

public class CglibProxy implements MethodInterceptor {//创建一个委托对象的属性private Object object;
//创建构造方法  在创建代理类的时候要委托类
public CglibProxy(Object object) {this.object = object;
}//创建一个构造方法 创建类的时候将委托类放入public Object createProxy(){//创建cglib的主类Enhancer ec = new Enhancer();//添加父类,父类就是委托类ec.setSuperclass(object.getClass());//设置cglib代理对象的类ec.setCallback(this);//创建代理对象并返回return ec.create();}//cglib代理执行的方法@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//创建返回值Object obj = false;try {//开启事务TxManage.begin();//调用委托类的方法obj = methodProxy.invokeSuper(o,objects);//提交事务TxManage.commit();}catch (Exception e){//回顾事务TxManage.rollback();}finally {TxManage.close();}return obj;}
}

 

创建一个新的业务层:不使用接口创建,里面写转账的方法:

测试:

动态代理不能代理没有接口的类:

更改cglib代理:

测试:

cglib是通过继承来实现的代理

 

 


http://chatgpt.dhexx.cn/article/VtI4anPB.shtml

相关文章

三种代理模式详解

文章目录 二、代理模式&#xff08;Proxy Pattern&#xff09;1、常见的几种代理模式&#xff1a;2、静态代理3、JDK动态代理4、CGLib代理5、CGLib和JDK动态代理的区别 二、代理模式&#xff08;Proxy Pattern&#xff09; 根据B站狂神视频整理&#xff1a;https://www.bilibil…

Spring的代理模式

1、代理模式 为什么要学习代理模式&#xff1f; 因为这就是springAOP的底层&#xff01;【springAOP和springMVC】 代理模式的分类&#xff1a; 静态代理动态代理 1.1、静态代理 角色分析&#xff1a; 抽象角色&#xff1a;一般会使用接口或者抽象类来解决真实角色&…

代理模式(Proxy模式)详解

在有些情况下&#xff0c;一个客户不能或者不想直接访问另一个对象&#xff0c;这时需要找一个中介帮忙完成某项任务&#xff0c;这个中介就是代理对象。例如&#xff0c;购买火车票不一定要去火车站买&#xff0c;可以通过 12306 网站或者去火车票代售点买。又如找女朋友、找保…

代理模式的详细介绍

国庆期间闲来无事&#xff0c;写了一个简单的小程序&#xff0c;小程序名称叫做 IT藏经楼。目的是分享这些年自己积累的一些学习材料&#xff0c;方面大家查找使用&#xff0c;包括电子书、案例项目、学习视频、面试题和一些PPT模板。里面所有材料都免费分享。目前小程序中只发…

代理模式

代理模式 代理模式应用场景模式结构实现方式 代理模式 控制着对于原对象的访问&#xff0c; 并允许在将请求提交给对象前后进行一些处理。 优点&#xff1a; 在客户端与目标对象之间起到一个中介作用和保护目标对象的作用&#xff1b;代理对象可以扩展目标对象的功能&#x…

代理模式详解

1. 代理模式 代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问&#xff0c;这样就可以在不修改原目标对象的前提下&#xff0c;提供额外的功能操作&#xff0c;扩展目标对象的功能。 代理模式一半包含三种角色&#x…

代理模式详细讲解

文章目录 一、什么是代理模式&#xff1f;二、 为什么使用代理模式&#xff1f;三、 代理模式的实现1、静态代理1.1、 创建公共的接口1.2、 创建被代理角色1.3、 创建代理角色1.4、 创建测试类 2、动态代理的实现2.1、 使用 JDK 的 Proxy 类实现动态代理1、 创建业务接口2、 创…

一文搞懂代理模式

代理模式 前言一、代理模式是什么&#xff1f;二、静态代理三、动态代理1.jdk动态代理&#xff08;接口代理&#xff09;2.cglib动态代理 前言 一、代理模式是什么&#xff1f; 代理模式是常见的设计模式之一&#xff0c;顾名思义&#xff0c;代理模式就是代理对象具备真实对象…

手机测试耳机音质的软件,耳机音质测试软件有哪些

耳机音质测试软件并不存在&#xff0c;因为耳机的音质对于人来说是主观的&#xff0c;你认为音质好的耳机&#xff0c;有的人却并不认为也很正常&#xff0c;国内外都没有恒定的耳机音质评判标准&#xff0c;大多数人认为音质好的耳机&#xff0c;那么它十有八九实际就是好的。…

软件测试的基本理论与方法

文章目录 前言软件测试基础1. 软件测试的概念2. 软件测试的目的 测试用例1. 测试用例的概念2. 测试用例的分类3. 测试用例的治理4. 测试用例的编制及使用5. 测试需求 软件生命周期1. 问题的定义及规划2. 需求分析3. 软件设计4. 程序编码5. 软件测试6. 运行维护7. 生命周期模型 …

固态硬盘测试软件有哪些,SSD测试软件有哪些?SSD测试软件盘点

在购买了固态硬盘(SSD)后&#xff0c;如果对商家或官方给出的诸如读写速度等关键性数据存在质疑的话&#xff0c;最好的解决方法莫过于通过SSD测试软件来找寻答案。那么&#xff0c;SSD测试软件有哪些&#xff1f;SSD测试软件哪个比较好用呢&#xff1f;针对上述问题&#xff0…

软件工程-软件测试-测试方法

软件工程-测试方法-白盒和黑盒测试 软件工程-软件测试 软件测试方法可以分为静态测试和动态测试。 静态测试 静态测试是指被测试程序不在程序上运行&#xff0c;而是采用人工检测和计算机辅助金泰分析的手段对程序进行检测。 静态测试方法 &#xff08;1&#xff09;人工检…

软件测试方法和技术有哪些?

软件测试方法和技术有哪些&#xff1f;包括软件测试基础、软件测试方法、软件测试流程和规范、单元测试与集成测试、系统测试、验收测试、软件本地化测试、测试自动化及其框架、白盒测试和黑盒测试等。 软件测试方法技术   软件测试方法&#xff1a; 一、等价类测试方法的…

软件测试方法汇总 - 从不同角度分析软件测试方法有哪些

1、从是否关心内部结构来看 &#xff08;1&#xff09;白盒测试&#xff1a;又称为结构测试或逻辑驱动测试&#xff0c;是一种按照程序内部逻辑结构和编码结构&#xff0c;设计测试数据并完成测试的一种测试方法。 &#xff08;2&#xff09;黑盒测试&#xff1a;又称为数据驱…

常见的软件测试方法有,常见的几种软件测试方法都有哪些

随着互联网的不断发展&#xff0c;越来越多的人也都开始学习软件测试的相关技术&#xff0c;而今天我们就一起来了解一下&#xff0c;常见的几种软件测试方法都有哪些。 1、单元测试 单元测试测试的是代码库的单元。 它们直接调用函数或单元&#xff0c;并确保返回正确的结果。…

Dynatrace系列之- 标记常见问题

Dynatrace系列之- 标记常见问题 在大型环境中&#xff0c;系统的某些方面可能会持续触发不必要的警报。这些告警可能来自非关键组件或者是非关键情况下的资源不足的问题。通常这些问题不需要人员响应。 为了减少此类警报并避免发出垃圾告警邮件&#xff0c;Dynatrace AI根因分…

什么是 Dynatrace 里的 Visually Complete 度量标准

Dynatrace 中的 Visually Complete 是一个度量标准&#xff0c;用于测量在加载过程中用户在页面上看到的内容。Visually Complete 指标是当一个用户看到页面上的所有重要元素并且它们正确地渲染时所测量的时间点。这意味着所有可见的文本、图像和视频都已加载并正确显示。该指标…

DevSecOps 团队请避免陷入这些可观测性陷阱

如果您发现难以管理跨越多个云运行不断变化的容器化工作负载的庞大基础架构&#xff0c;那么您并不孤单。 根据 Dynatrace 近期发布的一项研究&#xff0c;超过一半的组织的 DevSecOps 团队在可观测性数据方面感到痛苦。 多云和混合计算设置的兴起&#xff0c;使大部分组织能够…

前端性能分析工具Dyna Trace使用心得(转)

什么是dynatrace ajax “dynatrace ajax 是一个详细的底层追踪工具&#xff0c;它不仅可以显示所有请求和文件在网络中传输的时间&#xff0c;还会记录浏览器render&#xff0c;CPU消耗、JS解析和运行情况等详细的信息&#xff0c;而这些也只是dynatrace ajax的冰山一角。” 为…

使用dynatrace+showslow进行前端性能测试

原文&#xff1a;http://blog.csdn.net/zhangren07/article/details/6883617 1.背景 应用的性能测试与优化目前主要停留在服务器端的反馈&#xff0c;而对于前端性能标准的研究与测试相对比较空白&#xff0c;缺乏统一的标准与工具。众所周知&#xff0c;浏览器html组件的下载…