动态代理是 Java 中一种强大的技术,它允许在运行时创建代理类和对象。在 Java 中,主要有两种动态代理的实现方式:JDK 动态代理和 CGLIB 动态代理。下面分别介绍这两种方式的实例。
JDK 动态代理
JDK 动态代理是通过 java.lang.reflect
包中的 Proxy
类和 InvocationHandler
接口实现的。首先,我们需要定义一个实现了 InvocationHandler
接口的代理类,然后通过 Proxy.newProxyInstance
方法创建代理对象。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义接口
interface Hello {
void sayHello();
}
// 实现 InvocationHandler 接口的代理类
class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before method invocation");
Object result = method.invoke(target, args);
System.out.println("After method invocation");
return result;
}
}
// 测试
public class JDKDynamicProxyExample {
public static void main(String[] args) {
// 创建被代理的对象
Hello realSubject = new HelloImpl();
// 创建代理对象
Hello proxy = (Hello) Proxy.newProxyInstance(
Hello.class.getClassLoader(),
new Class[]{Hello.class},
new MyInvocationHandler(realSubject)
);
// 调用代理对象的方法
proxy.sayHello();
}
}
// 被代理的实际类
class HelloImpl implements Hello {
@Override
public void sayHello() {
System.out.println("Hello, world!");
}
}
在上面的例子中,MyInvocationHandler
是实现了 InvocationHandler
接口的代理类,通过它的 invoke
方法,在方法调用前后加入了额外的逻辑。Proxy.newProxyInstance
方法创建了代理对象,该对象实现了 Hello
接口。
CGLIB 动态代理
CGLIB(Code Generation Library)是一个代码生成库,它可以在运行时动态生成字节码,实现对类的增强。CGLIB 动态代理不要求目标对象实现接口,相比于 JDK 动态代理更加灵活。
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import net.sf.cglib.proxy.Enhancer;
// 被代理的类
class Hello {
public void sayHello() {
System.out.println("Hello, world!");
}
}
// 实现 MethodInterceptor 接口的代理类
class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method invocation");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method invocation");
return result;
}
}
// 测试
public class CGLIBDynamicProxyExample {
public static void main(String[] args) {
// 创建 Enhancer 对象
Enhancer enhancer = new Enhancer();
// 设置被代理的类
enhancer.setSuperclass(Hello.class);
// 设置回调函数
enhancer.setCallback(new MyMethodInterceptor());
// 创建代理对象
Hello proxy = (Hello) enhancer.create();
// 调用代理对象的方法
proxy.sayHello();
}
}
在这个例子中,MyMethodInterceptor
实现了 CGLIB 的 MethodInterceptor
接口,通过它的 intercept
方法,在方法调用前后加入了额外的逻辑。Enhancer
类用于生成代理对象,通过设置被代理的类、回调函数等参数,最后调用 create
方法生成代理对象。
总体而言,JDK 动态代理适用于接口代理,而 CGLIB 动态代理适用于类代理。选择使用哪种方式取决于具体的需求和场景。