java 动态代理实现

java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口实现。Proxy 类提供了创建动态代理类和实例的静态方法,而 InvocationHandler 接口需要用户实现,用于处理在代理实例上执行的方法调用。

实现步骤

  1. 定义一个或多个接口:被代理类需要实现的接口。
  2. 创建实现 InvocationHandler 接口的类 :在这个类中实现 invoke 方法,该方法将调用原始对象的对应方法,并可以在调用前后添加自定义的逻辑。
  3. 通过 Proxy 类的静态方法创建代理对象 :将接口类数组和实现了 InvocationHandler 接口的类的实例作为参数传递给 Proxy.newProxyInstance 方法。

示例

假设我们有一个接口 Greeting 和一个实现了该接口的类 SimpleGreeting,现在我们想要在不修改 SimpleGreeting 源代码的情况下,为其方法调用添加日志功能。

Greeting 接口

java 复制代码
public interface Greeting {  
    void sayHello(String name);  
}

SimpleGreeting 类

java 复制代码
public class SimpleGreeting implements Greeting {  
    @Override  
    public void sayHello(String name) {  
        System.out.println("Hello, " + name);  
    }  
}

InvocationHandler 实现

java 复制代码
import java.lang.reflect.InvocationHandler;  
import java.lang.reflect.Method;  
  
public class GreetingInvocationHandler implements InvocationHandler {  
    private final Object target;  
  
    public GreetingInvocationHandler(Object target) {  
        this.target = target;  
    }  
  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        System.out.println("Before method: " + method.getName());  
        Object result = method.invoke(target, args);  
        System.out.println("After method: " + method.getName());  
        return result;  
    }  
}

创建代理对象并测试

java 复制代码
import java.lang.reflect.Proxy;  
  
public class ProxyDemo {  
    public static void main(String[] args) {  
        Greeting realSubject = new SimpleGreeting();  
        Greeting proxyInstance = (Greeting) Proxy.newProxyInstance(  
                realSubject.getClass().getClassLoader(),  
                new Class<?>[] { Greeting.class },  
                new GreetingInvocationHandler(realSubject)  
        );  
  
        proxyInstance.sayHello("World");  
    }  
}

运行 ProxyDemomain 方法,将看到在调用 sayHello 方法前后分别输出了日志信息,而实际的方法调用则通过 InvocationHandlerinvoke 方法转发给了原始的 SimpleGreeting 实例。

注意事项

  • 动态代理主要用于代理接口,如果要代理类(没有实现接口),则需要使用其他技术,如 CGLIB。
  • 动态代理的性能开销比静态代理稍大,因为每次方法调用都涉及反射。
  • 动态代理提供了强大的灵活性和可扩展性,但应谨慎使用,以避免不必要的复杂性。

---- 文章由 文心一言 生成

相关推荐
DogDaoDao5 小时前
Android 硬件编码器参数完全指南:MediaCodec 深度解析
android·音视频·视频编解码·h264·硬编码·视频直播·mediacodec
二哈赛车手6 小时前
新人笔记---ApiFox的一些常见使用出错
java·笔记·spring
为何创造硅基生物6 小时前
C语言 结构体内存对齐规则(通俗易懂版)
c语言·开发语言
JohnnyDeng946 小时前
Android 自定义 View:Canvas 绘图与事件分发深度解析
android
吃好睡好便好6 小时前
在Matlab中绘制横直方图
开发语言·学习·算法·matlab
栗子~~6 小时前
JAVA - 二层缓存设计(本地缓冲+redis缓冲+广播所有本地缓冲失效) demo
java·redis·缓存
星寂樱易李6 小时前
iperf3 + Python-- 网络带宽、网速、网络稳定性
开发语言·网络·python
YDS8296 小时前
DeepSeek RAG&MCP + Agent智能体项目 —— RAG知识库的搭建和接口实现
java·ai·springboot·agent·rag·deepseek
仰泳之鹅7 小时前
【C语言】自定义数据类型2——联合体与枚举
c语言·开发语言·算法
之歆7 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript