Java静态代理和动态代理

本文深入浅出地介绍了Java中的代理模式,包括静态代理和动态代理。通过生活中的例子,解释了代理模式的作用和优势,如保护被代理对象信息、方法增强等。接着详细展示了静态代理的实现,强调了其在代码层面的局限性,如需手动创建多个代理类。然后,通过动态代理解决了这一问题,利用Java的类加载器和反射机制实现了动态创建代理类,降低了代码冗余。文章最后简要提到了CGLIB动态代理作为补充。
摘要由CSDN通过智能技术生成

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的动态代理,这个后面再说。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Survivor001

你可以相信我,如果你愿意的话

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值