静态代理

70 阅读3分钟

静态代理通过手动创建代理类,实现与目标对象相同的接口,在调用前后添加额外逻辑(如日志、事务),代码简单但需为每个类编写代理,适用于方法增强场景。


静态代理详解

1. 代理模式概述

代理模式是一种结构型设计模式,通过引入 代理对象 控制对真实对象的访问,核心目的是在不修改原始类的前提下,增强其功能(如日志记录、权限校验、性能监控等)。

2. 静态代理实现原理

  • 核心角色

    • 抽象接口(Subject) :定义真实对象和代理对象的共同行为。
    • 真实对象(RealSubject) :实现接口,执行业务逻辑。
    • 代理对象(Proxy) :实现接口,持有真实对象的引用,调用真实对象方法前后插入增强逻辑。
  • 类关系图

    +----------------+          +----------------+
    |   Subject      |          |   RealSubject  |
    +----------------+          +----------------+
    | +doAction():void |<------| +doAction():void |
    +----------------+          +----------------+
             ^
             |
    +----------------+
    |   Proxy        |
    +----------------+
    | -realSubject:RealSubject |
    | +doAction():void         |
    +----------------+
    

3. 代码示例

以下以数据库查询为例,演示静态代理如何实现日志记录:

步骤1:定义抽象接口
public interface DatabaseQuery {
    String query(String sql);
}
步骤2:实现真实对象
public class RealDatabaseQuery implements DatabaseQuery {
    @Override
    public String query(String sql) {
        // 真实数据库查询逻辑
        return "Result of: " + sql;
    }
}
步骤3:创建代理类
public class DatabaseQueryProxy implements DatabaseQuery {
    private RealDatabaseQuery realQuery;
​
    public DatabaseQueryProxy(RealDatabaseQuery realQuery) {
        this.realQuery = realQuery;
    }
​
    @Override
    public String query(String sql) {
        // 前置增强:记录日志
        System.out.println("Log: Start query with SQL -> " + sql);
​
        // 调用真实对象方法
        String result = realQuery.query(sql);
​
        // 后置增强:记录结果
        System.out.println("Log: Query result -> " + result);
        return result;
    }
}
步骤4:客户端调用
public class Client {
    public static void main(String[] args) {
        // 创建真实对象
        RealDatabaseQuery realQuery = new RealDatabaseQuery();
​
        // 创建代理对象
        DatabaseQuery proxy = new DatabaseQueryProxy(realQuery);
​
        // 通过代理执行查询
        proxy.query("SELECT * FROM users");
    }
}

输出结果

Log: Start query with SQL -> SELECT * FROM users
Log: Query result -> Result of: SELECT * FROM users

4. 静态代理的优缺点

优点缺点
1. 代码简单直观,易于理解和实现。1. 需为每个目标类编写代理类,代码冗余。
2. 功能增强与业务逻辑解耦。2. 接口方法变更时,需同步修改代理类。
3. 灵活控制目标对象的访问。3. 代理类数量多时维护成本高。

5. 适用场景

  • 少量类的增强:需为有限数量的类添加固定功能(如日志、事务)。
  • 接口方法稳定:接口方法不频繁变更,减少代理类维护成本。
  • 简单项目或原型开发:初期快速实现功能扩展,无需引入复杂框架。

6. 静态代理 vs 动态代理

对比维度静态代理动态代理(如JDK/CGLIB)
代理类生成方式手动编写代理类。运行时动态生成代理类(无需手动编码)。
代码冗余需为每个目标类创建代理类。一个代理类可代理多个接口或类。
维护成本接口变更时需修改代理类。自动适配接口变化,维护成本低。
灵活性低,适用于简单场景。高,支持复杂增强逻辑(如AOP)。

总结:静态代理通过显式编码实现功能增强,适合简单、小规模场景;动态代理则通过反射或字节码技术实现灵活代理,适用于大规模或复杂需求。理解二者差异有助于合理选择代理方案。