Java代理

2025 年 8 月 8 日 (已编辑)
616 字
4 分钟

参考文章

  1. 博客园-java动态代理实现与原理详细分析

前置知识

代理很简单, 就是引入一个中间人; 这个中间人不仅用于传递信息, 还可以进行过滤/其他调用等操作

这就好比 我通过朋友向老师提交作业, 朋友可能会顺一瓶可乐回来, 或者和老师聊聊天, 说说我的好话和坏话

代理组成:

  • Subject:抽象主题(接口)
  • RealSubject:真实主题(实现类)
  • Proxy:代理类(控制对真实主题的访问)

动态和静态代理

静态代理, 在编译时就已经将接口, 被代理类等确定下来; 在程序运行之前, 代理类的.class文件就已经生成

动态代理: 代理类在程序运行时创建的代理方式被成为动态代理; 动态代理的优势在于可以很方便的对代理类的函数进行统一的处理, 而不用修改每个代理类中的方法

核心类与接口

  • java.lang.reflect.Proxy:动态代理的主类
  • java.lang.reflect.InvocationHandler:调用处理器接口

例子

java
// 1. 定义业务接口
interface Service {
    void execute();
}

// 2. 实现业务接口
class RealService implements Service {
    public void execute() {
        System.out.println("真实服务执行");
    }
}

// 3. 实现调用处理器
class ServiceHandler implements InvocationHandler {
    private Object target; // 被代理对象

    public ServiceHandler(Object target) {
        this.target = target;
    }

    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {

        System.out.println("前置处理");
        Object result = method.invoke(target, args); // 调用真实方法
        System.out.println("后置处理");
        return result;
    }
}

// 4. 创建动态代理
public class Main {
    public static void main(String[] args) {
        // 创建真实对象
        Service realService = new RealService();

        // 创建调用处理器
        InvocationHandler handler = new ServiceHandler(realService);

        // 创建代理对象
        Service proxy = (Service) Proxy.newProxyInstance(
            Service.class.getClassLoader(), // 类加载器
            new Class[]{Service.class},    // 代理接口数组
            handler                        // 调用处理器
        );

        // 通过代理调用方法
        proxy.execute();
    }
}

方法调用流程

JavaReflection

代理类生成过程

  • 根据接口信息生成代理类的字节码
  • 使用类加载器加载生成的代理类
  • 通过反射创建代理类实例

代理使用条件

  • 目标包含invoke
  • invoke方法中调用get
  • readObject调用已有方法

重点

执行被代理对象的任何方法都会先触发代理类的invoke方法, 你从上面的方法调用流程可以很直观的看出来

嗯, 这里好像可以利用反序列化哦

文章标题:Java代理

文章作者:4reexile

文章链接:https://4reexile.github.io/posts/java/java%E4%BB%A3%E7%90%86[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。