浅析Java中静态代理和动态代理的应用与区别

 更新时间:2023年08月25日 16:13:59   作者:双木林啊  
代理模式在我们生活中很常见,而Java中常用的两个的代理模式就是动态代理与静态代理,这篇文章主要为大家介绍了二者的应用与区别,需要的可以参考下

一、静态代理

1、静态代理引入

代理模式在我们生活中很常见,比如我们购物,可以从生产工厂直接进行购物,但是在生活中往往不是这样,一般都是厂家委托给超市进行销售,而我们不直接跟厂家进行关联,这其中就引用了静态代理的思想,厂家相当于真实角色,超市相当于代理角色,我们则是目标角色。代理角色的作用其实就是,帮助真实角色完成一些事情,在真实角色业务的前提下,还可以增加其他的业务。AOP切面编程就是运用到了这一思想。

2、静态代理案例

写一个小小的案例,通过婚庆公司,来实现静态代理

/**
 * @ClassName StaticProxy
 * @Description TODO 静态代理(模拟婚庆公司实现)
 * @Author ZhangHao
 * @Date 2022/12/11 11:38
 * @Version: 1.0
 */
public class StaticProxy {
    public static void main(String[] args) {
        Marry marry = new WeddingCompany(new You());
        marry.happyMarry();
        //注意:真实对象和代理对象要实现同一个接口
    }
}
//结婚
interface Marry{
    //定义一个结婚的接口
    void happyMarry();
}
//你(真实角色)
class You implements Marry{
    @Override
    public void happyMarry() {
        System.out.println("张三结婚了!");
    }
}
//婚庆公司(代理角色)
class WeddingCompany implements Marry{
    //引入真实角色
    private Marry target;
    public WeddingCompany(Marry target){
        this.target = target;
    }
    @Override
    public void happyMarry() {
        //在结婚前后增加业务
        before();
        target.happyMarry();
        after();
    }
    private void before(){
        System.out.println("结婚之前:布置婚礼现场");
    }
    private void after(){
        System.out.println("结婚之后:收尾工作");
    }
}

对于Java中的Thread底层就使用的静态代理模式,源码分析

//Thread类实现了Runnable接口
public class Thread implements Runnable{
  //引入了真实对象
  private Runnable target;
  //代理对象中的构造器
  public Thread(Runnable target, String name) {
         init(null, target, name, 0);
  }
}

当我们开启一个线程,其实就是定义了一个真实角色实现了Runnable接口,重写了run方法。

public void TestRunnable{
    public static void main(String[] args){
      MyThread myThread = new MyThread();
      new Thread(myThread,"张三").start();
      //Thread就是代理角色,myThread就是真实角色,start()就是实现方法
    }
}
class MyThread implements Runnable{
   @Override
   public void run() {
     System.out.println("我是子线程,同时是真实角色");
   }
}

二、动态代理

1、动态代理的引入

上面使用到了静态代理,代理类是自己手工实现的,自己创建了java类表示代理类,同时要代理的目标类也是确定的,如果当目标类增多时,代理类也需要成倍的增加,代理类的数量过多,当接口中的方法改变或者修改时,会影响实现类,厂家类,代理都需要修改,于是乎就有了jdk动态代理。

2、动态代理的好处

  • 代理类数量减少
  • 修改接口中的方法不影响代理类
  • 实现解耦合,让业务功能和日志、事务和非事务功能分离

3、动态代理的实现步骤

  • 创建接口,定义目标类要完成功能。
  • 创建目标类实现接口。
  • 创建InvocationHandler接口实现类,在invoke()方法中完成代理类的功能。
  • 使用Proxy类的静态方法,创建代理对象,并且将返回值转换为接口类型。

以下是代码案例:

/**
 * @ClassName DynamicProxy
 * @Description TODO 动态代理
 * @Author ZhangHao
 * @Date 2022/12/11 15:11
 * @Version: 1.0
 */
public class DynamicProxy {
    public static void main(String[] args) {
        //创建目标对象
        Marry target = new You();
        //创建InvocationHandler对象
        MyInvocationHandler handler = new MyInvocationHandler(target);
        //创建代理对象
        Marry proxy = (Marry)handler.getProxy();
        //通过代理执行方法,会调用handle中的invoke()方法
        proxy.happyMarry();
    }
}
//创建结婚接口
interface Marry{
    void happyMarry();
}
//目标类实现结婚接口
class You implements Marry{
    @Override
    public void happyMarry() {
        System.out.println("张三结婚了!");
    }
}
//创建工具类,即方法增强的功能
class ServiceTools{
    public static void before(){
        System.out.println("结婚之前:布置婚礼现场");
    }
    public static void after(){
        System.out.println("结婚之后:清理结婚现场");
    }
}
//创建InvocationHandler的实现类
class MyInvocationHandler implements InvocationHandler{
    //目标对象
    private Object target;
    public MyInvocationHandler(Object target){
        this.target = target;
    }
    //通过代理对象执行方法时,会调用invoke()方法
    /**
     * @Param [proxy:jdk创建的代理类的实例]
     * @Param [method:目标类中被代理方法]
     * @Param [args:目标类中方法的参数]
     * @return java.lang.Object
    **/
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //增强功能
        ServiceTools.before();
        //执行目标类中的方法
        Object obj = null;
        obj = method.invoke(target,args);
        ServiceTools.after();
        return obj;
    }
    //通过Proxy类创建代理对象(自己手写的嗷)
    /**
     * @Param [ClassLoader loader:类加载器,负责向内存中加载对象的,使用反射获取对象的ClassLoader]
     * @Param [Class<?>[] interfaces: 接口, 目标对象实现的接口,也是反射获取的。]
     * @Param [InvocationHandler h: 我们自己写的,代理类要完成的功能。]
     * @return java.lang.Object
    **/
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),this);
    }
}

三、总结

代理分为静态代理和动态代理

静态代理需要手动书写代理类,动态代理通过Proxy.newInstance()方法生成

不管是静态代理还是动态代理,代理与被代理者都要实现两样接口,本质面向接口编程

代理模式本质上的目的是为了在不改变原有代码的基础上增强现有代码的功能

到此这篇关于浅析Java中静态代理和动态代理的应用与区别的文章就介绍到这了,更多相关Java静态代理和动态代理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于Java创建线程的2种方式以及对比

    关于Java创建线程的2种方式以及对比

    这篇文章主要给大家介绍了关于Java创建线程的2种方式以及对比的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-01-01
  • JavaWeb利用struts实现文件下载时改变文件名称

    JavaWeb利用struts实现文件下载时改变文件名称

    这篇文章主要为大家详细介绍了JavaWeb利用struts实现文件下载时改变文件名称的相关资料,需要的朋友可以参考下
    2016-06-06
  • Java8 Stream collect(Collectors.toMap())的使用

    Java8 Stream collect(Collectors.toMap())的使用

    这篇文章主要介绍了Java8 Stream collect(Collectors.toMap())的使用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • 深度解析Java中volatile的内存语义实现以及运用场景

    深度解析Java中volatile的内存语义实现以及运用场景

    这篇文章主要介绍了Java中volatile的内存语义实现以及运用场景,通过JVM的机制来分析volatile关键字在线程编程中的作用,需要的朋友可以参考下
    2015-12-12
  • Java中面向对象的知识点总结

    Java中面向对象的知识点总结

    Java是一门面向对象的语言。对象是Java程序中的基本实体。除了对象之外Java程序同样处理基本数据。下面这篇文章主要给大家总结了关于Java中面向对象的知识点,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-02-02
  • java 如何复制非空对象属性值

    java 如何复制非空对象属性值

    这篇文章主要介绍了java 如何复制非空对象属性值的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • java中最易犯错的特殊字符示例详解

    java中最易犯错的特殊字符示例详解

    这篇文章主要给大家介绍了关于java中最易犯错的特殊字符的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-09-09
  • JAVA Log 日志级别和使用配置示例

    JAVA Log 日志级别和使用配置示例

    本文介绍了Java中主流的日志框架,包括Logback和Log4j2,并详细解释了日志级别及其使用场景,同时,还提供了配置示例和使用技巧,如正确的日志记录方式、异常日志记录、性能优化以及环境特定的日志配置,本文给大家介绍的非常详细,感兴趣的朋友一起看看吧
    2025-11-11
  • SpringBoot使用Minio进行文件存储的实现

    SpringBoot使用Minio进行文件存储的实现

    本文主要介绍了SpringBoot使用Minio进行文件存储的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • Spark SQL关于性能调优选项详解

    Spark SQL关于性能调优选项详解

    这篇文章将为大家详细讲解有关Spark SQL性能调优选项,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获
    2023-02-02

最新评论