过 java.lang.reflect.Proxy
类和 java.lang.reflect.InvocationHandler
接口实现。Proxy
类提供了创建动态代理类和实例的静态方法,而 InvocationHandler
接口需要用户实现,用于处理在代理实例上执行的方法调用。
实现步骤
- 定义一个或多个接口:被代理类需要实现的接口。
- 创建实现
InvocationHandler
接口的类 :在这个类中实现invoke
方法,该方法将调用原始对象的对应方法,并可以在调用前后添加自定义的逻辑。 - 通过
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");
}
}
运行 ProxyDemo
的 main
方法,将看到在调用 sayHello
方法前后分别输出了日志信息,而实际的方法调用则通过 InvocationHandler
的 invoke
方法转发给了原始的 SimpleGreeting
实例。
注意事项
- 动态代理主要用于代理接口,如果要代理类(没有实现接口),则需要使用其他技术,如 CGLIB。
- 动态代理的性能开销比静态代理稍大,因为每次方法调用都涉及反射。
- 动态代理提供了强大的灵活性和可扩展性,但应谨慎使用,以避免不必要的复杂性。
---- 文章由 文心一言 生成