博客
关于我
面向接口的静态代理和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执行计划 EXPLAIN参数
    查看>>
    MySQL执行计划【explain】,看这一篇就够啦!
    查看>>
    Mysql执行计划字段解释
    查看>>
    mysql执行计划怎么看
    查看>>
    MySQL执行计划解读
    查看>>
    mysql执行顺序与索引算法
    查看>>
    mysql批量update优化_Mysql中,21个写SQL的好习惯,你值得拥有呀
    查看>>
    MYSQL批量UPDATE的两种方式
    查看>>
    mysql技能梳理
    查看>>
    MySQL报错ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘
    查看>>
    Mysql报错Packet for query is too large问题解决
    查看>>
    mysql报错级别_更改MySQL日志错误级别记录非法登陆(Access denied)
    查看>>
    Mysql报错:too many connections
    查看>>
    MySQL报错:无法启动MySQL服务
    查看>>
    mysql排序查询
    查看>>
    Mysql插入数据从指定选项中随机选择、插入时间从指定范围随机生成、Navicat使用存储过程模拟插入测试数据
    查看>>
    MYSQL搜索引擎
    查看>>
    mysql操作数据表的命令_MySQL数据表操作命令
    查看>>
    MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?
    查看>>