在 Java 中,动态代理可以使用两种主要的方式实现:JDK 动态代理和 CGLIB 动态代理。下面详细介绍这两种动态代理方式,并提供相应的 Java 代码示例。
JDK 动态代理:
JDK 动态代理是使用 Java 标准库中的 java.lang.reflect.Proxy
类来生成代理对象的机制。它要求目标类实现一个或多个接口,代理对象会实现这些接口,并将方法调用转发到 InvocationHandler
的实现类上。
- 创建一个接口,定义要被代理的方法。
- 创建一个实现
InvocationHandler
接口的类,实现invoke
方法来实现方法的拦截和增强逻辑。 - 使用
Proxy.newProxyInstance()
方法创建代理对象,传入目标类的类加载器、接口数组和实现InvocationHandler
的对象。
示例代码如下:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Hello {
void sayHello();
}
class MyInvocationHandler implements InvocationHandler {
private final Hello target;
public MyInvocationHandler(Hello target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Before calling sayHello()");
Object result = method.invoke(target, args);
System.out.println("After calling sayHello()");
return result;
}
}
public class JdkDynamicProxyExample {
public static void main(String[] args) {
Hello hello = new HelloImpl();
Hello proxyHello = (Hello) Proxy.newProxyInstance(
hello.getClass().getClassLoader(),
hello.getClass().getInterfaces(),
new MyInvocationHandler(hello)
);
proxyHello.sayHello();
}
}
class HelloImpl implements Hello {
@Override
public void sayHello() {
System.out.println("Hello, world!");
}
}
CGLIB 动态代理:
CGLIB(Code Generation Library)是一个字节码生成库,它可以在运行时动态生成类的子类,用于实现代理。CGLIB 动态代理要求目标类不是 final
类型,并且不需要实现接口。
- 导入 CGLIB 相关库。
- 创建一个继承目标类的子类,重写要被代理的方法,并在方法中添加拦截和增强逻辑。
- 使用 CGLIB 的
Enhancer
类创建代理对象。
示例代码如下:
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
class Hello {
public void sayHello() {
System.out.println("Hello, world!");
}
}
class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before calling sayHello()");
Object result = proxy.invokeSuper(obj, args);
System.out.println("After calling sayHello()");
return result;
}
}
public class CglibDynamicProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(Hello.class);
enhancer.setCallback(new MyMethodInterceptor());
Hello proxyHello = (Hello) enhancer.create();
proxyHello.sayHello();
}
}