Java 动态代理(JDK 自带)简单实现
本文最后更新于263 天前,其中的信息可能已经过时,如有错误请发送邮件到2192492965@qq.com

1. 前言

在 Java 开发中,动态代理是一种很有用的技术,尤其在 日志、权限管理、事务处理 这些场景下很常见。JDK 自带了一套动态代理机制,不需要我们自己写代理类,而是可以在运行时动态创建代理对象。

这篇文章会用一个简单的例子,来讲解 JDK 动态代理 是怎么工作的,同时也会分享一些优化方法,让代码更加简洁和高效。


2. 什么是 JDK 动态代理?

动态代理的核心有三个部分:

  1. 接口(Proxy Interface):规定了被代理对象可以执行哪些方法。
  2. 被代理对象(Target Object):真正要执行方法的类。
  3. InvocationHandler:拦截方法调用,在执行前后加上额外逻辑。

JDK 通过 Proxy.newProxyInstance() 这个方法,来动态生成代理对象。


3. 代码示例

3.1 定义接口

public interface ProxyBody {
    void execute();
}

3.2 被代理的类

public class ProxyBodyImpl implements ProxyBody {
    @Override
    public void execute() {
        System.out.println("ProxyBodyImpl.execute");
    }
}

3.3 定义 Wrapping(类似 AOP 切面)

import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class WrappingImpl implements Wrapping {
    @Override
    public void before(Object proxy, Method method, Object[] args) {
        System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss")));
    }

    @Override
    public void after(Object proxy, Method method, Object[] args) {
        System.out.println("执行完毕: " + method.getName());
    }
}

3.4 InvocationHandler 拦截方法

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ServiceInvocationHandler implements InvocationHandler {
    private final Object target;
    private final Wrapping wrapping;

    public ServiceInvocationHandler(Object target, Wrapping wrapping) {
        this.target = target;
        this.wrapping = wrapping;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        wrapping.before(proxy, method, args);
        Object result = method.invoke(target, args);
        wrapping.after(proxy, method, args);
        return result;
    }
}

3.5 创建代理对象的方法

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.lang.reflect.Proxy;

public class ProxyHelper {
    private static final Map<Class<?>, Object> CACHE = new ConcurrentHashMap<>();

    @SuppressWarnings("unchecked")
    public <T> T getProxyInstance(T target, Wrapping wrapping) {
        return (T) CACHE.computeIfAbsent(target.getClass(), clazz ->
            Proxy.newProxyInstance(
                clazz.getClassLoader(),
                target.getClass().getInterfaces(),
                new ServiceInvocationHandler(target, wrapping)
            ));
    }
}

3.6 代理工厂(使用单例模式)

public class ProxyHelperFactory {
    private static final ProxyHelper INSTANCE = new ProxyHelper();
    private ProxyHelperFactory() {}
    public static ProxyHelper getInstance() {
        return INSTANCE;
    }
}

3.7 运行测试

public class Main {
    public static void main(String[] args) {
        ProxyBody serviceInstance = new ProxyBodyImpl();
        Wrapping wrapping = new WrappingImpl();

        ProxyBody proxyInstance = ProxyHelperFactory.getInstance().getProxyInstance(serviceInstance, wrapping);
        proxyInstance.execute();
    }
}

4. 运行效果

执行 Main.main() 之后,会看到这样的输出:

2025.03.17 14:00:00
ProxyBodyImpl.execute
执行完毕: execute

表示:

  1. 方法执行前,输出当前时间。
  2. 调用 ProxyBodyImpl.execute() 方法。
  3. 方法执行后,打印方法名称。

5. 总结

JDK 自带的 动态代理 让我们可以在不修改原代码的情况下,添加一些功能,比如 日志、权限管理、事务处理

这里我们做了几点优化:

用缓存减少代理对象的重复创建
用单例模式管理代理对象
优化 Wrapping 逻辑,避免无效代码
封装代理创建逻辑,让代码更清晰


6. 动态代理能用在哪?

  • AOP(面向切面编程),如 Spring AOP
  • 日志记录,在方法执行前后自动打印日志
  • 权限控制,拦截请求,检查用户权限
  • 方法调用监控,统计方法的执行时间
如果觉得本文对您有所帮助,可以支持下博主,一分也是缘?
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
隐藏
换装