网站首页 > java教程 正文
背景
笔者前几天看了一个面试题 “说一下什么是代理模式?”,于是回忆了一下这个设计模式,并结合一篇旧文 《理理 Java 开发中常见的设计模式》,温故了一下这个知识点。
十年前看了好多遍的设计模式,死活处于学了忘、学不会的状态;如今随便翻到的某个 Java 技术点,都能快速反应出它们的前因后果。时光如梭,毕业已经十年了,这大概算是进入了卖油翁纯熟的技艺阶段了吧!
代理模式概述
代理模式类图。面向对象编程语言中,代理对象和委托对象都需要实现相同接口,同时代理对象关联一个真正的委托对象,客户端得到的是一个代理的引用,实则背后调用的是真正委托对象的方法:
代理类型。 对于有大量类需要代理的应用,这就是一种负担。一方面增加了工作量,而且还产生了大量相似的代理类,所以有了动态代理这个解决方案:不需要为每个类都创建一个代理类,只在需要使用代理的时候,通过反射机制动态地生成一个实现代理接口的匿名类的实例。代理的分类:动态代理和静态代理,即生成代理类的方式是什么。
动态代理的两种类型:JDKProxy 和 CGlib 两种,二者比对结果如下
类型原理特点JDKProxy运行时直接写Class字节码生成代理类效率高,反射执行效率低CodeGeneratorLibraryASM框架写 Class 字节码生成代理类效率低,FastClass 机制直接调用方法,执行效率高
Java 而言,ASM 就是字节码级别的编程,assembly ,即汇编语言。学过汇编的同学,有没有感觉很亲切呢?
JDKProxy。 JDK 是支持动态代理的,核心类为 Proxy
JDK 的 Proxy 实现动态代理,优势是,抽象统一的 InvocationHandler 实现类,完成公共的代理增强动作。然后参数是 targetInstance 。不需要定义 Proxy 实现类,直接通过动态代理生成代理类实例即可。
测试 JDKProxy 。根据这个类图,来编写一个动态代理的测试类如下。
第一步,定义代理接口类:
public interface Delegate {
void log();
}
第二步,定义代理接口实现类:
public class DelegateImp implements Delegate{
@Override
public void log() {
System.out.println("Class is "+this.getClass().getName());
}
}
第三步,编写测试类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Date;
public class ProxyTest {
public static void main(String[] args) {
//这里定义的是如何对委托类进行访问
DelegateImp imp = new DelegateImp();
InvocationHandler handler = new InvocationHandler() {
// proxy 这个类是最终的代理类
// 自定义的 InvocationHandler 需要指定具体的 target 目标对象的
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//调用委托类的方法之前的操作
System.out.println("Start to call "+method.getName()+",time is:"+new Date());
//调用委托类的方法
method.invoke(imp, args);
//调用委托类之后的操作
System.out.println("Finish to call "+method.getName()+",time is:"+new Date());
return null;
}
};
//创建一个代理类
Delegate proxy = (Delegate)Proxy.newProxyInstance(DelegateImp.class.getClassLoader(), DelegateImp.class.getInterfaces(), handler);
proxy.log();
}
}
运行结果:log 方法执行前后,多了一下增强动作。
Start to call log,time is:Mon Jan 20 10:59:54 CST 2020
Class is javastudy.DelegateImp
Finish to call log,time is:Mon Jan 20 10:59:54 CST 2020
装饰模式概述
装饰模式指的是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能。它是通过创建一个包装对象,也就是装饰来包裹真实的对象。(来自百度百科的定义)
《Head first 设计模式》中描绘的该模式的静态结构图为:
- 具体组件类和装饰类必须实现相同的顶层接口 Component;
- 具体装饰实现类包含一个具体组件的引用,即装饰类的构造过程需要传入一个具体的组件类,以便对原组件类进行装饰;
- 装饰类可以对被装饰者的行为增强,在之前或之后加上自己的动作。
编程启示录
仔细分析了一下,发现代理模式和装饰模式的区别有两点:
第一点,关联的类型不同。代理模式和装饰模式的区别,从类图结构上来看:
- 代理关联的是具体的委托对象;装饰着装饰的是装饰者的接口类型;
- 代理真正的委托对象,客户端是不知道的;装饰的具体对象,是由客户端来指定的。
第二点,目的不同。代理,着重是控制对委托对象的访问,由代理类本身决定谁是委托对象;装饰,是对被装饰对象的增强,由客户端指定对谁进行装饰。
另外,JDKProxy 动态代理的测试过程中,笔者想到的一些内容是:
JDKProxy 动态代理的核心是 InvokationHandler 的实现,它定义了如何对委托对象进行访问。如果在实际开发中,增强操作可以复用的话,这个接口的实现类并不会很多。但是,如果每个委托对象,都有自己的行为访问控制方式的话,那就跟静态代理没有什么区别了,因为需要为每个委托对象都创建一种 InvokationHandler 的实现类。
当然,就日常开发而言, InvokationHandler 基本上能够复用,实现类的数量不会太多。
猜你喜欢
- 2024-10-24 Java动态代理与静态代理以及它能为我们做什么
- 2024-10-24 Java 设计模式 之 代理模式 (1)(java设计模式之代理模式)
- 2024-10-24 Java设计模式:代理模式 vs. 装饰模式
- 2024-10-24 设计模式篇——代理模式详解(面试再问你代理模式,这么回答他)
- 2024-10-24 动态代理大揭秘,带你彻底弄清楚动态代理
- 2024-10-24 面试:Java的代理模式动态代理和静态代理区别,aop用的什么代理
- 2024-10-24 Java设计模式之代理模式(java代理类是什么)
- 2024-10-24 JAVA设计模式——代理模式(java编写代理服务)
- 2024-10-24 23种java设计模式之:门面模式、享元模式、代理模式
- 2024-10-24 Java 17中的动态代理:实现灵活的代理模式
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)