JDK静态&&动态代理

JDK静态&&动态代理

代理

类里面的类

eg:房东只有房;中介即收中介费,还管理后期的维修问题(不能把所有东西都堆给房东)

静态代理

包含三个角色:

接口类(抽象角色):定义共同的方法(比如 IUser)

目标类(真实角色):实现接口中的方法(比如 UserImpl)

代理类(代理角色):也实现接口,但在调用目标类方法前后加上“增强逻辑”(比如 UserProxy)

示例

接口类:

1
2
3
4
5
6
7
package com.test;

public interface  IUser {
    public void show();
    public void creat();
    public void update();
}

真实类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.test;

public class UserImpl implements IUser {
    @Override
    public void show() {
        System.out.println("展示");
    }

    @Override
    public void creat() {
        System.out.println("creat");
    }

    @Override
    public void update() {
        System.out.println("update");
    }
}

代理类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.test;

public class UserProxy implements IUser  {
    IUser user;

    public UserProxy(IUser user) {
        this.user = user;
    }

    @Override
    public void show() {
      user.show();
      System.out.println("调用了show");
    }

    @Override
    public void creat() {
        user.creat();
        System.out.println("调用了Creat");
    }

    @Override
    public void update() {
        user.update();
        System.out.println("调用了Update");
    }
}

执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.test;

import java.lang.reflect.Proxy;

public class ProxyTest {
    public static void main(String[] args) {
      //直接连接调用
       IUser user = new UserImpl();//接口类引用指向实现类对象
      //  user.show();


        //静态代理
        IUser userProxy = new UserProxy(user);//传进真正的对象
        userProxy.show();
        userProxy.creat();
    }
}

动态代理

  • 示例

    1
    2
    3
    4
    5
    6
    7
    8
    //动态代理
    //要代理的接口、要做的事情、classloader
    InvocationHandler userinvocationhandler = new UserInvocationHandler(user);
    IUser userProxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(),
            user.getClass().getInterfaces(),
            userinvocationhandler);
    userProxy.update();
    }
    1. Proxy.newProxyInstance()就是要新建一个动态代理类

    2. 查看传参

      代理接口、要传入的东西、类加载器classloader

      image-20251114202828469

      第一个是classloader,第二个是类的接口,第三个是调用处理器(传入的东西)

      前两个是系统固定给的参数,只有InvocationHandler类得自己写

  • InvocationHandler类:

    1
    2
    3
    public class UserInvocationHandler implements InvocationHandler {
        
    }

    image-20251114203424363

    爆红原因:

    image-20251114203452235

    需要重写invoke

    因为:

    1. JDK 动态代理的所有方法调用,本质上全部都被转发到 InvocationHandler.invoke()
    2. 如果你不重写 invoke(),代理对象调用方法时:
      • 没有任何逻辑可执行
      • 也无法调用真实对象
      • 相当于“没有代理”
    3. InvocationHandler是接口,不是父类,所以接口里面的方法需要实现,也就是通过invoke来实现

    重写之后:

    最重要的就是method

    image-20251114204034899

    不管外界传入什么,都要通过invoke来调用method方法

    代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    public class UserInvocationHandler implements InvocationHandler {
    
        IUser user;
    
        public UserInvocationHandler() {
        }
    
        public UserInvocationHandler(IUser user) {
            this.user = user;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("调用了"+method.getName());
            method.invoke(user, args);
            return null;
        }
    }

    通过动态调用,来将真实文件中的接口实现调用

    不用写上面那么多的静态代码(UserProxy),节约了代码

  • 流程:

    B.f(最终目的)

    A[O] ->O .abc

    O[O2]invoke->O2.f(使用B.f替换O2)———–>O[B]invoke->B.f

    所以A[O] ——->O .abc ———>B.f

  • 总结
    代理 一种设计模式不修改原有类 增加功能

    意义:
    少修改代码 适配强

    在反序列化漏洞中的作用:
    readObject>反序列化自动执行
    invoke>有函数调用

    拼接两条链(任意->固定)

对比

类型 本质 代码谁来写? 可代理方法数量 是否需要接口
静态代理 提前写死的代理类 你写代理类 固定(写几个代理几个) 要求接口或继承
动态代理 JVM 运行时生成代理类 JVM 自动生成 无限制,自动代理全部方法 JDK 要有接口(CGLIB 可无接口)

拓展

动态代理的核心思想,就是从“静态代理设计模式”演化出来的。它现在的意义主要是用于教学,帮助理解动态代理的核心思想

现代开发里,静态代理几乎被动态代理和 AOP 完全取代了

AOP

AOP(面向切面编程)就是:给方法“加功能”,但不修改原有代码

1
2
3
4
5
6
7
8
9
10
11
比如:在某个方法(打日志)执行前后自动,但是 不想修改这个方法的源码

AOP 就负责:
 👉 把这些“横切功能”自动插入到方法的执行过程前/后/周
 
就像吃饭的正常流程:点菜 → 做菜 → 上菜 → 吃饭
但是老板偷偷加了一些功能:
每次点菜前:欢迎语(before)
做菜后:卫生检查(after)

饭店厨师没有改自己的代码这些行为是系统自动加的。

AOP 技术是基于动态代理实现(动态代理就是 AOP 的底层)

Spring AOP 本质上就是:

1
2
3
4
5
6
7
代理对象(Proxy) → “拦截” → 调用真实对象

在 invoke() 里加:
    - before
    - after
    - around
    - afterThrowing

所以 AOP = 动态代理的“封装版”、“高级版”。


JDK静态&&动态代理
http://example.com/2025/11/14/JDK动态代理/
作者
Piggy Sprint
发布于
2025年11月14日
许可协议