在文章:
一文读懂Java中的设计模式——代理模式,以翻译场景举例,特别通俗易懂!-CSDN博客
中给大家介绍了Java的代理模式,以及静态代理的用法。接下来就为大家介绍动态代理。注意:本文涉及的 类EnglishProxy 和FrenchProxy源码在上篇文章中。完整的java代理模式源码下载地址如下:https://download.csdn.net/download/liwenxiang629/88650205
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。JDK中关于动态代理的重要api如下:
所谓静态代理也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。 但是静态代理的缺点也很明显,在程序规模稍大时,维护代理类的成本高,静态代理无法胜任!那么在这里我们就通过动态代理来解决静态代理维护成本高的问题。
例如我们有一个新的需求,需要增加给翻译结算的功能,怎么做呢?
最简单的方法就是分别在代理类 EnglishProxy 和FrenchProxy的talk方法里增加方法。目前只有两个类,这么做是比较容易实现的,当涉及需要修改多个类的时候,显然这种方式就不合适了,我们就可以通过动态代理来实现这个需求!
核心类的设计如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LanguageProxyHandler implements InvocationHandler {
private Object object;
public LanguageProxyHandler(Object p_object){
this.object = p_object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
method.invoke(object, args);
System.out.println("给翻译结算");
return null;
}
}
我们可以看到,动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke)
最后来看测试代码
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class DynamicProxyTest {
public static void main(String[] args) {
ITalk vtalk = new EnglishProxy();
//ITalk vtalk = new FrenchProxy();
InvocationHandler handler = new LanguageProxyHandler(vtalk);
ITalk proxyTalk = (ITalk)Proxy.newProxyInstance(vtalk.getClass().getClassLoader(),vtalk.getClass().getInterfaces(), handler);
proxyTalk.talk();
}
}
输出:
找一个会汉语和英语的翻译
默认中文交流
翻译把汉语翻译成英语
给翻译结算
我们可以看到,在没有修改类EnglishProxy 和FrenchProxy的前提下就实现了需求
通过JDK实现动态代理类也有小小的遗憾,那就是它只能为接口创建代理!如果想对没有实现接口的类创建代理则无能为力。为了解决这种情况,我们通常使用cglib技术,其在AOP(例如spring)和ORM(例如Hibernate)中有广泛的应用,在这里就不对cglib进行展开介绍了。Java代理模式关系总结如下:
我的每一篇文章都希望帮助读者解决实际工作中遇到的问题!如果文章帮到了您,劳烦点赞、收藏、转发!您的鼓励是我不断更新文章最大的动力!