首页 > 编程语言 >JAVA 静态代理 & 动态代理

JAVA 静态代理 & 动态代理

时间:2024-11-21 19:09:37浏览次数:1  
标签:JAVA 静态 morning 代理 接口 public 动态 Hello

Java中,代理模式是一种常见的设计模式,用于为某对象提供一种代理,以控制对该对象的访问。根据代理类的实现方式,可以分为静态代理和动态代理。以下将分别介绍这两种方式,并进行对比分析。

静态代理

静态代理是指在编译时期就已经确定了代理类的实现。代理类需要实现与目标对象相同的接口,并持有目标对象的引用,通过代理对象调用目标对象的方法。

静态代理的实现步骤

  1. 定义接口。
  2. 编写接口的实现类(目标类)。
  3. 编写代理类,实现接口并持有目标类的引用。
  4. 在代理类中,通过目标类的引用调用实际的方法。

示例代码

// 定义接口
public interface Hello {
    void morning(String name);
}

// 目标类
public class HelloWorld implements Hello {
    @Override
    public void morning(String name) {
        System.out.println("Good morning, " + name);
    }
}

// 代理类
public class HelloProxy implements Hello {
    // 内部维护一个目标代理对象的属性字段
    private Hello target;
    public HelloProxy(Hello target) {
        this.target = target;
    }

    @Override
    public void morning(String name) {
        System.out.println("Before method invoke...");
        target.morning(name); // 调用目标类方法
        System.out.println("After method invoke...");
    }
}

// 测试静态代理
public class Main {
    public static void main(String[] args) {
        Hello target = new HelloWorld();       // 创建目标对象
        Hello proxy = new HelloProxy(target); // 创建代理对象
        proxy.morning("Bob");                 // 调用代理方法
    }
}

输出:

Before method invoke...
Good morning, Bob
After method invoke...

优点

  • 结构简单,容易理解。
  • 代理类可以扩展目标类的功能(如添加日志、权限校验等)。

缺点

  • 每增加一个接口,都需要单独编写代理类,扩展性差。
  • 代理类的维护工作量较大。

动态代理

动态代理是指在运行时动态生成代理类,而不需要提前定义实现类。它的实现主要依赖于Java的java.lang.reflect.ProxyInvocationHandler

动态代理的实现步骤

  1. 定义接口。
  2. 创建InvocationHandler接口的实现类,用来处理方法调用。
  3. 使用Proxy.newProxyInstance()生成动态代理对象。

示例代码

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义接口
public interface Hello {
    void morning(String name);
}
// 测试动态代理
public class Main {
    public static void main(String[] args) {
        // 创建InvocationHandler
        InvocationHandler handler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Before method invoke...");
                if (method.getName().equals("morning")) {
                    System.out.println("Good morning, " + args[0]);
                }
                System.out.println("After method invoke...");
                return null;
            }
        };
        // 创建动态代理对象
        Hello hello = (Hello) Proxy.newProxyInstance(
            Hello.class.getClassLoader(),     // 类加载器
            new Class[] { Hello.class },      // 需要实现的接口
            handler                           // 方法调用处理器
        );
        // 调用代理方法
        hello.morning("Bob");
    }
}

输出

Before method invoke...
Good morning, Bob
After method invoke...

动态代理的核心:

  1. InvocationHandler接口:定义了代理逻辑的核心。
  2. Proxy.newProxyInstance():负责在运行时动态生成代理类并返回代理实例。

动态代理本质上是JVM在运行时生成代理类的字节码,并加载到内存中。

静态代理与动态代理的对比

特点 静态代理 动态代理
代理类实现方式 编译时定义代理类 运行时动态生成代理类
对接口的支持 每个接口需要单独实现代理类 可通用,只需实现InvocationHandler
代码扩展性 低,新增接口时需增加代理类 高,只需更改代理逻辑即可
性能开销 无需反射,性能较高 依赖反射调用,性能略低
应用场景 小型项目或接口稳定的场景 大型项目、动态扩展功能的场景

总结

  • 静态代理适用于小型项目,或者代理类相对固定的场景。
  • 动态代理适用于需要动态扩展功能或减少重复代码的场景。
  • 动态代理的灵活性更强,尤其是在AOP(面向切面编程)框架中广泛使用,如Spring框架中的动态代理。

动态代理的强大之处在于,它将代理逻辑与具体实现解耦,使得代码更加灵活、可维护,同时提供了更高的复用性。

标签:JAVA,静态,morning,代理,接口,public,动态,Hello
From: https://www.cnblogs.com/erosion2020/p/18561350

相关文章

  • 【BitMap】 java中实现BitMap位图 byte数组实现的bitmap位图
      转载自: https://blog.csdn.net/heshiyuan1406146854/article/details/122687988 /***byte数组实现的bitmap**@authorSXD*@date2024/11/21*/publicclassMyBitmap{privatebyte[]buckets;publicMyBitmap(intmaxNum){this.ini......
  • java中的异常,异常处理
    什么是异常?异常是程序运行过程中所遇到的错误或者不正常的情况,可能会导致程序终止或者出错。在Java中所有的异常都继承自一个throwable的类,它有error和exception两个子类,而且分为编译错误和运行时错误。为什么需要异常处理?出现异常后,导致程序后的代码都无法执行。从而造成......
  • 点餐管理系统设计与实现(Java+SpringBoot+MySql)
              目录第1章 绪论1.1选题动因1.2目的和意义1.3论文结构安排第2章 开发环境与技术2.1MySQL数据库2.2 Tomcat介绍2.3 vue技术2.4 SpringBoot框架第3章 系统分析3.1可行性分析3.1.1操作可行性分析3.1.2经济可行性分析......
  • 新手使用代理ip介入代码怎么写?
    Python语言(使用requests库为例)在上述代码中:首先导入了requests库,它是Python中常用的用于发送HTTP请求的库。然后定义了一个字典格式的proxy变量,用于配置代理IP的相关信息,分别针对http和https协议指定代理的地址和端口(这里的http://和https://要按照你获取的代理的实际协议情......
  • 【Flinkcdc问题解决】java.lang.NoClassDefFoundError: org/apache/flink/shaded/guav
    1.环境介绍Flink1.17+Flinkcdc2.2.12.问题描述使用Flink1.17和Flinkcdc2.2.1环境进行数据加工,但是报以上错误,原因是版本不匹配,flinkcdc2.2.1用的是guava18,但是flink1.17用的是guava30,导致冲突。3.问题解决添加flink-sql-connector-mysql-cdc依赖<dependen......
  • vue2-代理服务器&插槽
    解决跨域问题配置代理服务器代理服务器位于前端应用(客户端)和真实的后端服务器之间。当配置了代理服务器后,前端应用的请求不再直接发送到后端服务器,而是发送到代理服务器。代理服务器在接收到请求后,会根据预先配置的规则将请求转发到真正的后端服务器。例如,在Vue项目的开发服......
  • JavaScript网页设计案例:动态交互与用户体验提升
        随着前端开发技术的不断发展,JavaScript已经成为现代网页设计中不可或缺的工具。通过JavaScript,开发者可以为用户提供更为流畅、动态的交互体验,让网页不仅具备美观的视觉效果,更能提高用户的参与感和功能实用性。    本文将通过一个实际案例展示如何使用JavaS......
  • Java中子类构造时可以做的事
    在Java中,当子类的构造方法运行时,第一行默认会调用父类的构造方法(隐式调用super()),或者由显式调用指定的父类构造方法(如super(args...))。这是Java语言规范的一部分,目的是确保在子类实例化之前,父类部分的初始化能够完成。虽然这种调用机制是固定的,但仍有一些方式可以在构造方......
  • 【老白学 Java】Warship v2.0(一)
    Warshipv2.0(一)文章来源:《HeadFirstJava》修炼感悟。上一篇,简版的「Warship」项目终于完工。从本章开始,老白准备在简版基础上进行升级改造,逐步打造出「Warshipv2.0」。开篇前,老白先介绍一下「数组列表」对象,它是这个项目不可缺少的重要工具。如果师兄们感兴趣,可以......
  • Java批量解析微信dat文件,微信图片
    以下是java代码,直接可用,不用手动计算异或值此处的jdk版本需要1.8以上…,另外两个参数(解析文件路径和输出路径)需要改成自己的哦~此处的原理是判断图片文件的十六进制特征码。第一种:weChatImgRevert.javapackagecom;importjava.io.File;importjava.io.FileInputStream;impor......