Java--静态代理和动态代理

代理

代理就是通过代理对象去访问实际的目标对象,比如我们在生活中租房,可以直接找房东,也可以通过某些租房平台去租房,通过租房平台的这种方式就是代理。在java中这种租房平台就被叫做代理类,代理类不仅能实现目标对象,还能增加一些额外的功能。

静态代理

什么叫做静态代理?

静态代理就是在代码运行之前,这个代理类就已经存在了。

例子

在这里插入图片描述

首先,需要创建一个租房的通用接口

package com.sxl.staticProxy;
//租房接口
public interface Rent {
    public void rent();
}

然后,我们需要一个被代理类,也就是需要出租房子的房东

package com.sxl.staticProxy;

//房东出租房屋
public class Landlord implements Rent{
    /**
     * 声明一个被代理类,需要重写接口中的rent方法
     */
    @Override
    public void rent() {
        System.out.println("房东已经出租房屋!");
    }
}

随即,我们需要写一个代理类,也就是中介

package com.sxl.staticProxy;

//代理,中介帮助房东出租房屋
/**
 *   声明一个代理类,要和被代理类继承同一个接口
 *   且要重写接口中的rent方法
 */
public class Proxy implements Rent{
    
    private Rent r;

    public Proxy(Rent r) {
        this.r = r;
    }

    @Override
    public void rent() {
        System.out.println("中介正在寻找房源...");
        kanfang();
        r.rent();
        System.out.println("中介已经帮助完成租房!");
        shoufei();
    }

    public void kanfang(){
        System.out.println("中介带领前去看房...");
    }

    public void shoufei(){
        System.out.println("中介收取费用!");
    }
}

最后,租客前来寻找中介租房

package com.sxl.staticProxy;
//租客前来租房
public class Test {
    public static void main(String[] args) {
        Landlord l=new Landlord();
        Proxy p=new Proxy(l);
        p.rent();
    }
}

运行结果
在这里插入图片描述

这样,我们就可以通过代理来完成租房子了

静态代理的优点

  1. 真实角色的操作可以更加纯粹,而不用过多的关注公共业务
  2. 代理角色可以去完成公共业务,实现了业务的分工
  3. 公共业务发生拓展的时候,更加便于拓展和管理

静态代理的缺点

  • 由于静态代理在代码运行之前就已经存在代理类,因此对于每一个代理对象都需要建一个代理类去代理,当需要代理的对象很多时就需要创建很多的代理类,严重降低程序的可维护性,开发效率也会大大降低。

动态代理

动态代理是指代理类不是写在代码中,而是在运行过程中产生的

基于Jdk的动态代理

底层实现

  • 通过实现 InvocationHandler 接口创建自己的调用处理器;
  • 通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类;
  • 通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型;
  • 通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。

基于Cglib的动态代理

cglib是一个java字节码的生成工具,它动态生成一个被代理类的子类,子类重写被代理的类的所有不是final的方法。
在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

基于javassist的动态代理(不做了解)

总结

静态代理比较容易理解, 需要被代理的类和代理类实现自同一个接口, 然后在代理类中调用真正实现类, 并且静态代理的关系在编译期间就已经确定了。而动态代理的关系是在运行期间确定的。静态代理实现简单,适合于代理类较少且确定的情况,而动态代理则给我们提供了更大的灵活性。

JDK 动态代理所用到的代理类在程序调用到代理类对象时才由 JVM 真正创建,JVM 根据传进来的业务实现类对象以及方法名 ,动态地创建了一个代理类的 class 文件并被字节码引擎执行,然后通过该代理类对象进行方法调用。我们需要做的,只需指定代理类的预处理、调用后操作即可。

静态代理和动态代理都是基于接口实现的, 而对于那些没有提供接口只是提供了实现类的而言, 就只能选择 CGLIB 动态代理了。
在这里插入图片描述

JDK 动态代理和 CGLIB 动态代理的区别

  • JDK 动态代理基于 Java 反射机制实现, 必须要实现了接口的业务类才能用这种方法生成代理对象。
  • CGLIB 动态代理基于 ASM 框架通过生成业务类的子类来实现。
  • JDK 动态代理的优势是最小化依赖关系,减少依赖意味着简化开发和维护并且有 JDK 自身支持。还可以平滑进行 JDK 版本升级,代码实现简单。
  • 基于 CGLIB 框架的优势是无须实现接口,达到代理类无侵入,我们只需操作我们关系的类,不必为其它相关类增加工作量,性能比较高。

描述代理的几种实现方式? 分别说出优缺点?

代理可以分为 “静态代理” 和 “动态代理”,动态代理又分为 “JDK 动态代理” 和 “CGLIB 动态代理” 实现。
1.静态代理:
代理对象和实际对象都继承了同一个接口,在代理对象中指向的是实际对象的实例,这样对外暴露的是代理对象而真正调用的是 Real Object.

优点:可以很好的保护实际对象的业务逻辑对外暴露,从而提高安全性。
缺点:不同的接口要有不同的代理类实现,会很冗余

2.JDK 动态代理:

为了解决静态代理中,生成大量的代理类造成的冗余;
JDK 动态代理只需要实现 InvocationHandler 接口,重写 invoke 方法便可以完成代理的实现.
jdk 的代理是利用反射生成代理类 Proxyxx.class 代理类字节码,并生成对象
jdk 动态代理之所以只能代理接口是因为代理类本身已经 extends 了 Proxy,而 java 是不允许多重继承的,但是允许实现多个接口

优点:解决了静态代理中冗余的代理实现类问题。
缺点:JDK 动态代理是基于接口设计实现的,如果没有接口,会抛异常。
3.CGLIB 代理:
由于 JDK 动态代理限制了只能基于接口设计,而对于没有接口的情况,JDK 方式解决不了;
CGLib 采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑,来完成动态代理的实现。实现方式实现 MethodInterceptor 接口,重写 intercept 方法,通过 Enhancer 类的回调方法来实现。
CGLib 在创建代理对象时所花费的时间却比 JDK 多得多,所以对于单例的对象,因为无需频繁创建对象,用 CGLib 合适,反之,使用 JDK 方式要更为合适一些。
由于 CGLib 由于是采用动态创建子类的方法,对于 final 方法,无法进行代理。

优点:没有接口也能实现动态代理,而且采用字节码增强技术,性能也不错。
缺点:技术实现相对难理解些。

Lombok

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值