推荐答案
在 Java 中,实现动态代理的方式主要有以下两种:
- JDK 动态代理:基于接口的动态代理,使用
java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现。 - CGLIB 动态代理:基于类的动态代理,使用 CGLIB 库来生成目标类的子类,从而实现代理。
本题详细解读
JDK 动态代理
JDK 动态代理是 Java 标准库提供的一种动态代理机制,它只能代理实现了接口的类。JDK 动态代理的核心是 Proxy 类和 InvocationHandler 接口。
实现步骤
- 定义一个接口。
- 实现该接口的目标类。
- 实现
InvocationHandler接口,编写代理逻辑。 - 使用
Proxy.newProxyInstance()方法创建代理对象。
示例代码
// www.javascriptcn.com code example
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface Subject {
void request();
}
class RealSubject implements Subject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
class DynamicProxyHandler implements InvocationHandler {
private Object target;
public DynamicProxyHandler(Object target) {
this.target = target;
}
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;
}
}
public class JDKDynamicProxyExample {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();
InvocationHandler handler = new DynamicProxyHandler(realSubject);
Subject proxy = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
handler
);
proxy.request();
}
}CGLIB 动态代理
CGLIB(Code Generation Library)是一个强大的高性能代码生成库,它可以在运行时扩展 Java 类和实现接口。CGLIB 动态代理通过生成目标类的子类来实现代理,因此它不需要目标类实现接口。
实现步骤
- 定义一个目标类。
- 实现
MethodInterceptor接口,编写代理逻辑。 - 使用
Enhancer类创建代理对象。
示例代码
// www.javascriptcn.com code example
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
class RealSubject {
public void request() {
System.out.println("RealSubject: Handling request.");
}
}
class CglibProxyInterceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method " + method.getName());
return result;
}
}
public class CglibDynamicProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new CglibProxyInterceptor());
RealSubject proxy = (RealSubject) enhancer.create();
proxy.request();
}
}总结
- JDK 动态代理:适用于代理实现了接口的类,使用标准库,无需引入第三方依赖。
- CGLIB 动态代理:适用于代理没有实现接口的类,需要引入 CGLIB 库,性能通常优于 JDK 动态代理。
根据具体需求选择合适的动态代理方式。