动态代理(Dynamic Proxy)是一种在运行时生成代理对象的机制,该代理对象可以在运行时动态地处理被代理对象的方法调用。与静态代理相比,动态代理无需提前为每个被代理的类编写一个专门的代理类,而是在运行时动态生成代理对象,使得代理的过程更加灵活和通用。
在 Java 中,动态代理主要通过 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口实现。以下是动态代理的关键组成部分:
InvocationHandler
接口:InvocationHandler
接口是动态代理的核心。它只定义了一个方法invoke
,该方法在代理对象调用方法时被调用。invoke
方法接收三个参数:
Object proxy
:代理对象。Method method
:被代理的方法。Object[] args
:方法的参数。
invoke
方法的实现确定了在调用代理对象的方法时要执行的逻辑,包括是否调用被代理对象的方法、在方法调用前后执行其他逻辑等。Proxy
类:Proxy
类是用于创建动态代理对象的工具类。它提供了静态方法newProxyInstance
,用于在运行时创建代理对象。newProxyInstance
方法接收三个参数:
ClassLoader loader
:类加载器,用于加载生成的代理类。Class<?>[] interfaces
:被代理对象实现的接口。InvocationHandler h
:实现了InvocationHandler
接口的对象,即代理对象在方法调用时执行的逻辑。
newProxyInstance
方法返回一个实现了指定接口的代理对象。- 示例:下面是一个简单的动态代理示例,假设有一个接口
Subject
和其实现类RealSubject
:
importjava.lang.reflect.InvocationHandler; importjava.lang.reflect.Method; importjava.lang.reflect.Proxy; interfaceSubject { voidrequest(); } classRealSubjectimplementsSubject { publicvoidrequest() { System.out.println("RealSubject: Handling request."); } } classDynamicProxyHandlerimplementsInvocationHandler { privateObjectrealSubject; publicDynamicProxyHandler(ObjectrealSubject) { this.realSubject=realSubject; } publicObjectinvoke(Objectproxy, Methodmethod, Object[] args) throwsThrowable { System.out.println("Dynamic Proxy: Before invoking method."); Objectresult=method.invoke(realSubject, args); System.out.println("Dynamic Proxy: After invoking method."); returnresult; } } publicclassDynamicProxyExample { publicstaticvoidmain(String[] args) { RealSubjectrealSubject=newRealSubject(); InvocationHandlerdynamicProxyHandler=newDynamicProxyHandler(realSubject); SubjectproxySubject= (Subject) Proxy.newProxyInstance( Subject.class.getClassLoader(), newClass[]{Subject.class}, dynamicProxyHandler ); proxySubject.request(); } }
在上述示例中,DynamicProxyHandler
类实现了 InvocationHandler
接口,定义了在代理对象方法调用前后执行的逻辑。然后,通过 Proxy.newProxyInstance
方法创建了一个实现了 Subject
接口的动态代理对象,该代理对象在调用 request
方法时会执行 DynamicProxyHandler
中定义的逻辑。
动态代理的优势在于它的通用性,能够代理任何实现了接口的类,并且无需生成特定的代理类文件。这种机制在很多框架和库中得到了广泛应用,例如在 AOP(面向切面编程)中,动态代理可以用于在方法调用前后执行额外的逻辑。