博客
关于我
面向接口的静态代理和java动态代理
阅读量:786 次
发布时间:2019-03-25

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

静态代理

代理模式概述

代理模式是一种常见的设计模式,其核心思想是在不改变目标对象的情况下,通过引入一个间接对象(代理)来装饰或增强目标对象的功能。这种模式通常用于当我们想对目标对象的某些方法进行额外处理或监控,而不会对原始业务逻辑造成太大影响时。

静态代理实现

在静态代理中,代理类(Proxy)与目标对象(RealObject)之间通常存在继承关系。代理类中包含一个引用(通常是通过构造器设置),这个引用指向目标对象。这样,代理类可以调用目标对象的方法,并在其中插入自己的逻辑。

代码示例
interface Interface {    void doSomething();    void somethingElse(String arg);}class RealObject implements Interface {    @Override    public void doSomething() {        System.out.println("Real doSomething");    }    @Override    public void somethingElse(String arg) {        System.out.println("Real somethingElse " + arg);    }}class SimpleProxy implements Interface {    private Interface proxied;    public SimpleProxy(Interface proxied) {        this.proxied = proxied;    }    @Override    public void doSomething() {        System.out.println("Proxy doSomething before");        proxied.doSomething();        System.out.println("Proxy doSomething after");    }    @Override    public void somethingElse(String arg) {        System.out.println("Proxy somethingElse before");        proxied.somethingElse(arg);        System.out.println("Proxy somethingElse after");    }}class SimpleProxyDemo {    public static void consumer(Interface iface) {        iface.doSomething();        iface.somethingElse("biu biu");    }    public static void main(String[] args) {        consumer(new RealObject()); // 直接调用        System.out.println(" ====== ");        consumer(new SimpleProxy(new RealObject())); // 使用静态代理    }}

静态代理特点

  • 优点:简单易实现,直接在代理方法中添加额外逻辑。
  • 缺点:当目标对象需要对接口进行扩展时,可能需要重新编写所有接口方法,这会导致开发工作量增加,尤其是在接口多变的情况下。

动态代理

动态代理概述

动态代理是一种更灵活的实现代理模式的方式。与静态代理不同,动态代理不需要预先知道目标对象的所有方法,而是在运行时动态地处理方法调用。这种方法通过反射机制实现,能够支持接口的动态扩展。

动态代理实现

动态代理的实现依赖于两个核心组件:

  • InvocationHandler:这个类必须实现InvocationHandler接口,其主要职责是在方法调用前、执行过程中和方法调用后执行自定义逻辑。
  • Proxy.newProxyInstance():使用Java反射API生成动态代理对象,这个过程需要指定目标接口和InvocationHandler。
  • 代码示例
    import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;class DynamicProxyHandler implements InvocationHandler {    private Object proxied;    public DynamicProxyHandler(Object proxied) {        this.proxied = proxied;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        System.out.println("Method: " + method.getName());        System.out.println("Arguments: " + (args != null ? args : ""));        System.out.println("---        try {            return method.invoke(proxied, args);        } catch (Throwable e) {            System.out.println("Error occurred: " + e.getMessage());            throw e;        }        System.out.println("After method execution");        return null;    }}class SimpleDynamicProxy {    public static void consumer(Interface iface) {        iface.doSomething();        iface.somethingElse("biu biu");    }    public static void main(String[] args) {        RealObject real = new RealObject();        consumer(real); // 直接调用        System.out.println(" ============== ");        // 使用动态代理生成代理对象        Interface proxy = (Interface) Proxy.newProxyInstance(            Interface.class.getClassLoader(),             new Class[] { Interface.class },             new DynamicProxyHandler(real)        );        consumer(proxy); // 通过动态代理调用    }}

    动态代理特点

    • 优点:能够灵活地支持任意接口的动态扩展,无需提前知道所有方法。
    • 缺点:反射操作可能影响性能,尤其是在频繁调用方法的情况下。

    两种代理模式的对比

    特性 静态代理 动态代理
    实现方式 通过直接继承接口实现 通过反射和InvocationHandler实现
    方法调用控制 在方法体内直接添加逻辑 在调用处理器中动态处理方法
    接口扩展支持 需要重新实现所有接口方法 支持接口的动态扩展
    代理对象生成方式 使用构造器或工厂类 使用Proxy.newProxyInstance()
    性能影响 有一定的性能开销,但可以预先优化 反射操作会引入额外性能开销

    个人感受

    静态代理和动态代理各有优劣,静态代理简单易懂,适合接口较为稳定和小变动的情况。动态代理则更灵活,适合接口可能发生变化或需要动态扩展功能的情况。作为开发者,根据具体需求选择合适的代理模式至关重要。

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

    你可能感兴趣的文章
    Mysql 知识回顾总结-索引
    查看>>
    Mysql 笔记
    查看>>
    MySQL 精选 60 道面试题(含答案)
    查看>>
    mysql 索引
    查看>>
    MySQL 索引失效的 15 种场景!
    查看>>
    MySQL 索引深入解析及优化策略
    查看>>
    MySQL 索引的面试题总结
    查看>>
    mysql 索引类型以及创建
    查看>>
    MySQL 索引连环问题,你能答对几个?
    查看>>
    Mysql 索引问题集锦
    查看>>
    Mysql 纵表转换为横表
    查看>>
    mysql 编译安装 window篇
    查看>>
    mysql 网络目录_联机目录数据库
    查看>>
    MySQL 聚簇索引&&二级索引&&辅助索引
    查看>>
    Mysql 脏页 脏读 脏数据
    查看>>
    mysql 自增id和UUID做主键性能分析,及最优方案
    查看>>
    Mysql 自定义函数
    查看>>
    mysql 行转列 列转行
    查看>>
    Mysql 表分区
    查看>>
    mysql 表的操作
    查看>>