Java设计模式(动态代理模式和责任链模式)

news/2024/5/19 6:39:42 标签: 设计模式, 反射, java, spring

动态代理的意义在于生成一个占位,代理真实对象,从而控制正式对象的访问。代理的作用是在真实对象访问之前或者之后加入对应的逻辑,或者根据其他的规则控制是否使用真实对象。代理需分为两步:代理对象和真实对象建立代理关系;实现代理对象的代理逻辑方法。在java中有多种动态代理机制,如JDK、CGLIB、Javassist等。

1. JDK动态代理

该方法需要借助一个接口才能产生代理对象,首先定义接口:
在这里插入图片描述
随后提供实现类来实现接口:
在这里插入图片描述
在JDK动态代理中,实现代理逻辑类必须实现java.lang.reflect.InvocationHandler接口,其里面定义一个invoke方法,并提供接口数组用于下挂代理对象。
在这里插入图片描述
在这里插入图片描述
第一步:建立代理对象和真实对象的关系
使用bind方法完成,方法里面先用类的属性target保存真实对象,通过如下代码建立生成代理对象。
在这里插入图片描述
newProxyInstance方法包含3个参数:
第一个是类加载器,使用target本身的类加载器;第二个将生成的动态代理对象下挂在那些接口下;第三个是定义实现方法逻辑的代理类,this表示当前对象,必须实现InvocationHandler接口的invoke方法,是代理逻辑方法的现实方法。
第二步:实现代理逻辑方法
invoke的三个参数含义如下所示。
proxy:代理对象,是bind方法生成的对象;method:当前调度的方法;args:调度方法的参数。
测试JDK动态代理:
在这里插入图片描述
首先通过bind方法绑定代理关系,然后在代理对象调度方法时进入代理的逻辑,测试结果如下:
在这里插入图片描述

2. CGLIB动态代理

由于JDK动态代理需要提供接口,而CGLIB动态代理不需要接口,只需要一个非抽象类就可实现动态代理。
在这里插入图片描述
用到CGLIB的Enhancer,通过设置超类的方法,setCallback方法设置哪个类为代理类。参数this意味着是当前对象,用this这个对象实现接口的方法,返回代理对象。测试一下CGLIB动态代理:
在这里插入图片描述

3. 拦截器

使用JDK动态代理实现一个拦截器的逻辑,先定义拦截器接口Interceptor:
在这里插入图片描述
定义三个方法,三个方法的参数:proxy代理对象,target真实对象,method方法,args为运行方法参数。
before方法返回boolean值,在真实对象前调用。当返回为true时,则返回真实对象的方法;当返回为false则调用around方法。随后调用after方法。
实现接口Interceptor的实现类:
在这里插入图片描述
在JDK动态代理中使用拦截器的代码如下:
在这里插入图片描述
在这里插入图片描述
以上代码执行过程:
1.在bind方法中用JDK动态代理绑定一个对象,然后返回代理对象。
2.如果没有设置拦截器则直接反射真实对象的方法,然后结束;否则进行第三步;
3.通过反射生成拦截器并准备使用它。
4.调用拦截器的before方法,当返回为true则反射原来的方法否则运行拦截器的around方法。
5.调用拦截器的after方法
6.返回结果。
拦截器的工作流程:
在这里插入图片描述
拦截器进一步简化代理是使用方法:
在这里插入图片描述

4. 责任链模式

当一个对象在一条链上被多个拦截器拦截处理,我们把这样的设计模式称为责任链模式,用于一个对象在多个角色中传递。
例如:
一个程序员需要请假一周。如果把请假申请单看成 个对象,那么它需要经过项目经理、部门经理、人事等多个角色的审批,每个角色都有机会通过拦截这个申请单进行审批或者修改。这时就要考虑提供项目经理、部门经理和人事的处理逻辑,所以需要提供三个拦截器,而传递的则是请假申请单。
在这里插入图片描述
可以考虑用层层代理来实现,就是当申请单(target )走到项目经理处,使用第 个动态代理 proxyl 。当它走到部门经理处,部门经理会得到 个在项目经理的代理 proxyl 基础上生成的 proxy2 来处理经理的逻辑。当它走到人事处,会在 proxy2 基础生成 proxy3。
在这里插入图片描述
责任链拦截器接口的定义:
在这里插入图片描述
在这里插入图片描述
测试责任链上的多拦截器:
在这里插入图片描述
测试结果如下:
在这里插入图片描述
责任链模式的优点在于我们可以在传递链上加入新的拦截器,增加拦截逻辑,其缺点是会增加代理和反射,而代理和反射的性能不高。


http://www.niftyadmin.cn/n/1865516.html

相关文章

Java设计模式(观察者模式)

观察者模式又称为发布订阅模式,是对象的行为模式。观察者模式定义了一对多的依赖关系,让多个观察者对象同时监视着被观察者的状态,当被观察者的状态发生变化会通知所有观察者 并让其自动更新自己。观察者模式示例: 类似这样&…

Java设计模式(工厂模式和抽象工厂模式)

1.普通工厂模式 有个IProduct 产品接口 ,它下面有 5个实现类Product1、Product2、 Product3 、Product4、Product5。它们属于1个大类,可以通过1个工厂去管理它们的生成,但是由于类型不同,所以初始化有所不同 。为了方便使用产品工…

Java设计模式(建造者模式)

建造者模式属于对象的创建模式。可以将一个产品的内部表象(属性〉与产品的生成过程分割开来,从而使 建造过程生成具有不同的内部表象的产品对象。Builder 模式是种分步构建对象的模式。 实例: 首先,创建一个 TicketHe per 对象&am…

认识Mybatis核心组件

持久层可以将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏(大部分的重要数据都会有相关的备份机制),在断电或者其他情况下,重新开启系统仍然可以读取这些数据。Mybatis 最大的成功主要有三点&#…

MyBatis的解析和运行原理

MyBatis运行过程分为两步: 读取配置文件缓存到Configuration对象,用以创建SqlSessionFactory;SqlSession的执行过程 1. 构建SqlSessionFactory过程 SqlSessionFactory是MyBatis的核心类之一,提供创建MyBatis的核心接口SqlSessi…

装配SpringBean

1.依赖注入的三种方式 实际环境中实现 IoC 容器的方式主要分为两大类, 一类是依赖查找,依赖查找是通过资源定位,把对应的资源查找回来。另一类则是依赖注入,Spring主要使用的是依赖注入。依赖注入可分为3种方式: 构造…

Spring与数据库编程

1. 传统JDBC的缺点 一般的JDBC代码如下: 传统的JDBC代码中含有大量的异常处理语句,使得代码繁杂。 2. 配置数据库资源 在实际工作中,大部分会配置成为数据库连接池,我们既可以使用 Spring 内部提供的类,也可以使…

虚拟机的三种通讯方式及具体实施

1. 桥接模式 这种方式最简单,直接将虚拟网卡桥接到一个物理网卡上面。在此种模式下,虚拟机内部的网卡直接连到了物理网卡所在的网络上,可以想象为虚拟机和host机处于对等的地位,在网络关系上是平等的,没有谁在谁后…