当前位置:网站首页>代理模式详解
代理模式详解
2022-06-24 19:30:00 【伏加特遇上西柚】
代理模式详解
1、代理模式概念
我很忙,忙的没空理你,那你要找我呢,就先找我的代理人吧,那代理人总要知道被代理人能做哪些事情不能做哪些事情吧,那就是两个人具备同一个接口,被代理人虽然不想干活,但是代理的人能干活呀。
生活中的房屋中介

2、代理模式分类
静态代理:
【定义】
在程序运行之前,代理类.class文件就已经被创建
【实现】
由程序员创建或特定工具自动生成源代码,在对其编译
动态代理:
【定义】
程序运行时通过反射机制动态创建的,对方法的【增强】,不需要修改源码
【实现】
基于接口:JDK动态代理
基于子类:CGLib动态代理
2.1 静态代理
【1】目标
使用静态代理的方式,完成通过房产中介租房的操作;
【2】实现
生活中的房屋中介抽象:

步骤:
1、创建项目;
2、定义接口:HouseAgencyCompany及接口中租房的方法:rentingHouse;
3、定义房主类:HouseOwner 中介类 HouseProxy均实现接口HouseAgencyCompany;
4、租客类Customer调用HouseProxy完成租房
【2.2】定义HouseAgencyCompany
package com.test.spring;
/** * @Description:中介公司 */
public interface HouseAgencyCompany {
/** * @Description 租房子 */
void rentingHouse();
}
【2.3】定义HouseOwner、HouseProxy
package com.test.spring;
/** * @Description:房东 */
public class HouseOwner implements HouseAgencyCompany {
@Override
public void rentingHouse() {
System.out.println("房东:签合同");
}
}
package com.test.spring;
/** * @Description:中介 */
public class HouseProxy implements HouseAgencyCompany{
private HouseOwner houseOwner;
public HouseProxy() {
this.houseOwner = new HouseOwner();
}
@Override
public void rentingHouse() {
System.out.println("中介:我带你去看房子");
System.out.println("中介:这个房子价格很便宜");
houseOwner.rentingHouse();
System.out.println("中介:欢迎下次光临");
}
}
【2.4】定义Customer
package com.test.spring;
import org.junit.Test;
/** * @Description:租客 */
public class Customer {
@Test
public void needHouse(){
HouseOwner houseOwner = new HouseOwner();
houseOwner.rentingHouse();
System.out.println("=============================");
HouseAgencyCompany houseAgencyCompany = new HouseProxy();
houseAgencyCompany.rentingHouse();
}
}
【2.5】运行结果
2.2 动态代理概述
代理类在程序运行时创建的方式被成为动态代理。也就是说,代理类并不是在Java代码中定义的,而是在运行时根据我们在Java代码中的动态生成的。相比于静态代理,动态代理的优势在于可以很方便的对代理类的函数进行统一的处理,而不用修改每个代理类的函数。
2.2.1 jdk动态代理
2.2.1.1 jdk动态代理:
被代理的类必须基于接口
java.lang.reflect.Proxy:
Java动态代理机制的主类,提供了一组静态方法来为一组接口动态地生成代理类及其实例。
//方法1: 该方法用于获取指定动态代理对象所关联的调用处理器
static InvocationHandler getInvocationHandler(Object proxy)
//方法2:该方法用于获取关联于指定类装载器和一组接口的动态代理对象
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
//方法3:该方法用于判断指定类对象是否是一个动态代理类
static boolean isProxyClass(Class cl)
//方法4:该方法用于为指定类装载器、一组接口及调用处理器生成动态代理对象:1、类加载器 2、接口数组、调用处理器(增强部分的业务代码)
static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)
java.lang.reflect.InvocationHandler:
调用处理器接口,它自定义了一个invoke方法,用于集中处理在动态代理对象上的方法调用,通常在该方法中实现对委托类的代理访问。每次生成动态代理对象时都需要指定一个实现了该接口的调用处理器对象。
InvocationHandler的核心方法:
//该方法负责集中处理动态代理类上的所有方法调用。
//第一个参数是代理对象,第二个参数是被调用的方法对象,第三个方法是调用参数。
//调用处理器根据这三个参数进行预处理或分派到委托类实例上反射执行。
Object invoke(Object proxy, Method method, Object[] args)

2.2.1.2 实现
2.2.1.2.1 代理接口
/** * @Description:中介公司 */
public interface HouseAgencyCompany {
/** * @Description 租房子 */
void rentingHouse();
}
2.2.1.2.2 房东类实现代理接口
/** * @Description:房东 */
public class HouseOwner implements HouseAgencyCompany {
@Override
public void rentingHouse() {
System.out.println("房东:签合同");
}
}
2.2.1.2.3 消费者类
/** * @Description:租客 */
public class Customer {
HouseOwner houseOwner = new HouseOwner();
@Test
public void needHouse(){
System.out.println("=============================");
//第一个参数:目标类的加载器,第二个参数:目标类的接口,第三个参数:调用处理器
HouseAgencyCompany houseAgencyCompany = (HouseAgencyCompany) Proxy.newProxyInstance(
HouseAgencyCompany.class.getClassLoader(),
houseOwner.getClass().getInterfaces(),
new InvocationHandler() {
//第一个参数:代理类,
//第二个参数:执行的目标方法,这里指的是:rentingHouse
//第三参数:方法参数
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置增强
System.out.println("中介公司:我安排中介带你去看房子");
Object invoke = method.invoke(houseOwner, args);
//后置增强
System.out.println("中介公司:欢迎下次光临");
return invoke;
}
});
houseAgencyCompany.rentingHouse();
}
}
2.2.1.2.4 结果

2.2.2 cglib动态代理
2.2.2.1 思考
如果目标类没有实现接口呢?
那么就无法使用JDK的动态代理,因此这种方式有其局限性,必须实现一个接口。
可以使用的方案:
使用CGLIB动态代理:基于子类(包含本类)
net.sf.cglib.proxy.Enhancer
Enhancer类是CGLib中的一个字节码增强器,作用用于生成代理对象,跟上一章所学的Proxy类相似,常用方式为:
//方法1:该方法用于为指定目标类、回调对象 1、类的类型,2、调用处理器
public static Object create(Class type, Callback callback)
net.sf.cglib.proxy.MethodInterceptor
///第一个:代理类,第二个是:执行的目标方法,第三个:方法参数,第四个:方法的代理
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
2.2.2.2实现
2.2.2.2.1房东类
/** * @Description:房东 */
public class HouseOwner {
public void rentingHouse() {
System.out.println("房东:签合同");
}
}
2.2.2.2.2消费者类
/** * @Description:租客 */
public class Customer {
@Test
public void needHouse(){
//第一个参数:被代理类的类型 第二个参数:拦截方法
HouseOwner houseOwner = (HouseOwner) Enhancer.create(
HouseOwner.class,
new MethodInterceptor() {
@Override
//第一个:代理类,第二个是:执行的目标方法,第三个:方法参数,第四个:方法的代理
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("房东儿子:我爸身体不好,让我来带i看房子");
methodProxy.invokeSuper(o, objects);
System.out.println("房东儿子:我爸身体不好,后面有什么事情你可以找我");
return null;
}
});
houseOwner.rentingHouse();
}
}
2.2.2.2.3结果

2.2.2.3小结
1、Cglib动态代理:基于类,无需实现接口;
2、被代理的目标类不能被final修饰
2.2.3动态代理小结
通过动态代理可以完成对已有方法的功能的增强:
1、JDK动态代理
要求:
被代理对象至少实现一个接口
应用场景:
被代理对象有接口
2、CGLIB动态代理
要求:
被代理类上不能用static、final修饰
应用场景:
被代理对象没有实现接口
边栏推荐
- (to be added) games101 job 7 improvement - knowledge you need to know to realize micro surface model
- 拖动拖动拖动
- Byte software testing basin friends, you can change jobs. Is this still the byte you are thinking about?
- leetcode_ one thousand three hundred and sixty-five
- Graduation design of phase 6 of the construction practice camp
- 双链表实现
- 是真干不过00后,给我卷的崩溃,想离职了...
- 我国SaaS产业的发展趋势与路径
- ST表+二分
- 心楼:华为运动健康的七年筑造之旅
猜你喜欢

架构实战营 第 6 期 毕业设计
![[featured] how do you design unified login with multiple accounts?](/img/df/9b4fc11a6971ebe8162ae84250a782.png)
[featured] how do you design unified login with multiple accounts?

【论】Deep learning in the COVID-19 epidemic: A deep model for urban traffic revitalization index

SAP接口debug设置外部断点

Opengauss kernel: simple query execution

将二维数组方阵顺时针旋转90°

cv2导包时报Could not find a version that satisfies the requirement cv2 (from versions: none)

leetcode:1504. 统计全 1 子矩形的个数

Fuzhou business office of Fujian development and Reform Commission visited the health department of Yurun university to guide and inspect the work

I really can't do it. After 00, I collapsed and wanted to leave
随机推荐
Detailed installation and use of performance test tool wrk
Summary of papers on traveling salesman problem (TSP)
Li Kou daily question - day 25 -496 Next larger element I
Datakit agent realizes unified data aggregation in LAN
心楼:华为运动健康的七年筑造之旅
leetcode:1504. 统计全 1 子矩形的个数
[theory] deep learning in the covid-19 epic: a deep model for urban traffic revitalization index
01--- conditions for interference of two trains of waves at the meeting place
Byte software testing basin friends, you can change jobs. Is this still the byte you are thinking about?
Object. Defineproperty and reflect Fault tolerance of defineproperty
想当测试Leader,这6项技能你会吗?
【论】A deep-learning model for urban traffic flow prediction with traffic events mined from twitter
拖动拖动拖动
多线程收尾
平衡二叉搜索树
suspense组件和异步组件
[精选] 多账号统一登录,你如何设计?
That is to say, "live broadcast" is launched! One stop live broadcast service with full link upgrade
I really can't do it. After 00, I collapsed and wanted to leave
03--- antireflective film