博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java静态代理和动态代理
阅读量:2048 次
发布时间:2019-04-28

本文共 4052 字,大约阅读时间需要 13 分钟。

Java静态代理和动态代理

什么是代理?

代理是一种设计模式。通过代理对象间接的反问被代理对象。(是的就是这么简单)

怎么理解呢?

举个例子:
小明*(被代理对象)*去详情了,想约女孩出来看电影代理事务),但是不想自己去找女孩,这时候找到媒婆代理对象)去传话,达到约会的目的。
在这里插入图片描述
我们通过上图想一想,代理的好处和作用。

  1. 为什么小明不自己去找小美说呢? ---->
    加入小明是个丑八怪,那直接去找小美,那不是凉凉。找媒婆的话就能直接把话带到且让自己相貌啥的不直接被小美知道。
    同理:通过代理对象实现代理事务,大大的保障了被代理对象信息安全。(484很容易理解了)
  2. 通过媒婆告诉小美有啥好处呢?
    你想想媒婆那嘴多能说,见到小美不得给小明先夸一波啥对吧,让小明更有魅力了。
    同理:代理对象在不入侵被代理对象的前提下,对其进行方法增强。
  3. 代理对象为什么不直接实现代理事务,还要代理对象干嘛?
    小明通过媒婆去找小美约会,最终还是小明跟小美约会。
    同理:代理对象实现代理事务最终还是调用的代理对象的事务。

通过上述生动的讲述,是不是很容易理解了什么是代理了?为什么需要代理了?下面通过代码层面彻底分析和了解下代理。

Java代理分为静态代理动态代理

两者有什么区别呢?我们先介绍完,再去分析(介绍完就很容易理解了)。

静态代理

通过上面的了解我们可以知道,想要实现代理是不是得满足几个条件:

  1. 对象:代理对象(媒婆)、被代理对象(小明)、代理事务(请小美去看电影这件事)
  2. 代理对象需要实现被代理对象的功能,所以代理对象需要实现跟被代理对象一样的方法。(媒婆找小美说话,说的就是请小美去看电影这件事,这件事和小明想说的是一样的)
  3. 代理对象需要集成被代理对象的继承类。(就是说被代理对象集成了AA,被代理对象实现时也需要集成AA,这个很好理解)
  4. 代理对象时间的代理事务本质上就是使用被代理对象的事务,则需要初始化被代理对象。(媒婆找到小美说去看电影,最终去的还是小明,实现事务的还是小明)

有了几点我们开始代码层面实现静态代理:

public interface SayToWatchTv {   public void sayToWatchTv();}被代理对象小明:跟小美说去看电影。/** * 代理对象-- 小明 on 2021/3/23. */public class NoProxyClass implements SayToWatchTv{    public void sayToWatchTv() {        System.out.println("小美我们去看电影吧");    }}代理对象媒婆,需要继承和小明一样的接口,且实现代理事物,但是最终还是调用的小明对象的实现方法/** * Created by  on 2021/3/23. * 代理对象媒婆 */public class ProxyClass implements SayToWatchTv{    NoProxyClass noProxyClass = new NoProxyClass(); // 初始化被代理对象    public void sayToWatchTv() {        noProxyClass.sayToWatchTv(); // 最终还是调用了被代理对象的方法    }}public class MainClass {    public static void main(String[] args) {        ProxyClass proxyClass =new ProxyClass();        proxyClass.sayToWatchTv();    }}

结果:

在这里插入图片描述

看到这是不是感觉静态代理tm也太简单了吧,神经病吧,为啥我不直接调用被代理对象的方法哦。还绕这个弯路。

那现在对照着代理的优点我们分析下:

  1. 如果有天老板对你说,小明在对小美邀请前,还去理头发了,把这个事务写进去。但是小明类这边你不要动,代码上个员工写的。
    — > 这个时候我们是不是可直接在代理对象中去实现是吧。(代理对象在不入侵被代理对象的前提下,对其进行方法增强)
/** * Created by  on 2021/3/23. * 代理对象媒婆 */public class ProxyClass implements SayToWatchTv{    NoProxyClass noProxyClass = new NoProxyClass();    public void sayToWatchTv() {        System.out.println("小明去理了发");        noProxyClass.sayToWatchTv();    }}

在这里插入图片描述

2. 很容易看出来,main方法里面直接调用的是代理对象,而不是被代理对象。同理:通过代理对象实现代理事务,大大的保障了被代理对象信息安全。

上面就是静态代理。我们设想一下,现在我们代理对象是程序员在知道被代理对象信息之后,手动创建的代理类。那要是系统里面有很多需要带的对象,使用静态代理是不是需要手动创建很多代理对象才行。这样代理冗余太多。太杂了,而且太耗资源了。那么有没有一种方法,可以不用手动创建代理对象,虽然我事先不知道被代理对象,但是我可以通过传参数的形式动态的去创建代理类呢?

答案是肯定的:这就是我们接下来要说的动态代理

动态代理

至于静态代理和动态代理的区别上面都说过了,也容易理解:动态创建代理类。

那么需要怎样去动态的去实现动态代理内呢?
想一想:
1.需要动态创建代理类,那就需要能动态构造类,那我们可以使用到java的类类加载器ClassLoader。
2.之前说了代理类最终还是使用的被代理对象的方法,但是现在代理对象我们是参数传入的,我们实现不知道需要代理啥类,有什么方法。所以我们需要从参数类中获取这些信息。那我们可以用到java的类反射机制。

被代理接口public interface SayToWatchTv {   public void sayToWatchTv();}被代理对象实现类/** * 代理对象-- 小明 on 2021/3/23. */public class NoProxyClass implements SayToWatchTv{    public void sayToWatchTv() {        System.out.println("小美我们去看电影吧");    }}代理类/** * Created by Administrator on 2021/3/23. */public class ProxyDT implements InvocationHandler{    //这个就是我们要代理的真实对象    SayToWatchTv  sayToWatchTv;   // 被代理对象接口     //构造方法,给我们要代理的真实对象赋初值    public SayToWatchTv getProxy(SayToWatchTv sayToWatchTv) {   // 用于构建代理类        this.sayToWatchTv = sayToWatchTv;        Object proxy = Proxy.newProxyInstance(sayToWatchTv.getClass().getClassLoader(), // 类加载器                                                                         sayToWatchTv.getClass().getInterfaces(),// 反射机制获取类信息                                                                         this); //被代理对象接口        return (SayToWatchTv) proxy;    }    // 用于出发调用代理事务    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        Object res = method.invoke(sayToWatchTv,args);        return res;    }public class MainClass {    public static void main(String[] args) {        ProxyDT proxyDT = new ProxyDT();  // 初始化代理类        NoProxyClass noProxyClass =new NoProxyClass();  // 需要被代理的类        SayToWatchTv sayToWatchTv = proxyDT.getProxy(noProxyClass);        sayToWatchTv.sayToWatchTv();      }}}

结果

在这里插入图片描述
动态代理有几个核心点:
1.动态构建代理类。 Proxy.newProxyInstance
2.main方法中调用sayToWatchTv时,就是触发了invoke方法.而该方法的 本质就是调用了被代理的是实现方法。
所以动态代理实现的原理其实就是静态代理的原则,只是运用了类加载器和反射等机制,实现动态创建代理类。
上面说的JDK实现的动态代理。还有中方式是基于CGLIB的动态代理,这个后面再说。

转载地址:http://sjhof.baihongyu.com/

你可能感兴趣的文章
Leetcode C++《热题 Hot 100-46》739.每日温度
查看>>
Leetcode C++《热题 Hot 100-47》236.二叉树的最近公共祖先
查看>>
Leetcode C++《热题 Hot 100-48》406.根据身高重建队列
查看>>
《kubernetes权威指南·第四版》第二章:kubernetes安装配置指南
查看>>
Leetcode C++《热题 Hot 100-49》399.除法求值
查看>>
Leetcode C++《热题 Hot 100-51》152. 乘积最大子序列
查看>>
Leetcode C++《热题 Hot 100-57》139. 单词拆分
查看>>
Leetcode C++《热题 Hot 100-62》621. 任务调度器
查看>>
Leetcode C++《热题 Hot 100-65》207. 课程表
查看>>
[Kick Start 2020] Round A 1.Allocation
查看>>
[Kick Start 2020] Round A 2.Plates
查看>>
Leetcode C++ 《第181场周赛-1》 5364. 按既定顺序创建目标数组
查看>>
Leetcode C++ 《第181场周赛-2》 1390. 四因数
查看>>
阿里云《云原生》公开课笔记 第一章 云原生启蒙
查看>>
阿里云《云原生》公开课笔记 第二章 容器基本概念
查看>>
阿里云《云原生》公开课笔记 第三章 kubernetes核心概念
查看>>
阿里云《云原生》公开课笔记 第四章 理解Pod和容器设计模式
查看>>
阿里云《云原生》公开课笔记 第五章 应用编排与管理
查看>>
阿里云《云原生》公开课笔记 第六章 应用编排与管理:Deployment
查看>>
阿里云《云原生》公开课笔记 第七章 应用编排与管理:Job和DaemonSet
查看>>