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。
  • 动态代理的性能开销比静态代理稍大,因为每次方法调用都涉及反射。
  • 动态代理提供了强大的灵活性和可扩展性,但应谨慎使用,以避免不必要的复杂性。

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

相关推荐
豆奶特浓61 分钟前
Java面试生死局:谢飞机遭遇在线教育场景,从JVM、Spring Security到AI Agent,他能飞吗?
java·jvm·微服务·ai·面试·spring security·分布式事务
Kaede67 分钟前
MySQL中如何使用命令行修改root密码
android·mysql·adb
珑墨28 分钟前
【唯一随机数】如何用JavaScript的Set生成唯一的随机数?
开发语言·前端·javascript·ecmascript
周杰伦fans38 分钟前
C# - Task 是什么?想象一下你在餐厅点餐
服务器·开发语言·c#
芳草萋萋鹦鹉洲哦41 分钟前
【tauri+rust】App会加载白屏,有时显示在左上角显示一小块,如何优化
开发语言·后端·rust
前端世界43 分钟前
float 还是 double?用储罐体积计算带你看懂 C 语言浮点数的真实世界坑
java·c语言·开发语言
豐儀麟阁贵1 小时前
8.5在方法中抛出异常
java·开发语言·前端·算法
Bro_cat1 小时前
Java基础
java·开发语言·面试
滨HI01 小时前
C++ opencv简化轮廓
开发语言·c++·opencv
明君879971 小时前
Flutter 图纸标注功能的实现:踩坑与架构设计
android·ios