推荐答案
JDK 动态代理和 CGLIB 是 Java 中两种常见的代理技术,它们的区别主要体现在以下几个方面:
实现方式:
- JDK 动态代理基于接口实现,要求目标类必须实现至少一个接口。
- CGLIB 基于继承实现,通过生成目标类的子类来创建代理对象,不要求目标类实现接口。
性能:
- JDK 动态代理在生成代理对象时速度较快,但在调用代理方法时性能稍差。
- CGLIB 在生成代理对象时速度较慢,但在调用代理方法时性能较好。
依赖:
- JDK 动态代理是 Java 标准库的一部分,无需额外依赖。
- CGLIB 需要引入第三方库(如
cglib或spring-core)。
适用场景:
- JDK 动态代理适用于基于接口的代理场景。
- CGLIB 适用于没有接口的类或需要代理 final 方法的场景。
本题详细解读
JDK 动态代理
JDK 动态代理是 Java 标准库提供的一种代理机制,基于 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口实现。它的核心原理是通过反射机制在运行时动态生成代理类,并将方法调用转发到 InvocationHandler 的实现类中。
特点:
- 只能代理实现了接口的类。
- 代理类继承自
java.lang.reflect.Proxy,并实现目标接口。 - 调用代理方法时,会通过
InvocationHandler的invoke方法进行拦截。
示例代码:
// www.javascriptcn.com code example
public interface UserService {
void save();
}
public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("保存用户");
}
}
public class UserServiceProxy implements InvocationHandler {
private Object target;
public UserServiceProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("前置处理");
Object result = method.invoke(target, args);
System.out.println("后置处理");
return result;
}
public static void main(String[] args) {
UserService target = new UserServiceImpl();
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new UserServiceProxy(target)
);
proxy.save();
}
}CGLIB
CGLIB(Code Generation Library)是一个强大的代码生成库,它通过生成目标类的子类来实现代理。与 JDK 动态代理不同,CGLIB 不要求目标类实现接口,因此可以代理普通类。
特点:
- 可以代理没有实现接口的类。
- 通过继承目标类生成代理类。
- 可以代理 final 方法(但无法修改 final 方法的行为)。
示例代码:
// www.javascriptcn.com code example
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class UserService {
public void save() {
System.out.println("保存用户");
}
}
public class UserServiceInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置处理");
Object result = proxy.invokeSuper(obj, args);
System.out.println("后置处理");
return result;
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new UserServiceInterceptor());
UserService proxy = (UserService) enhancer.create();
proxy.save();
}
}总结对比
| 特性 | JDK 动态代理 | CGLIB |
|---|---|---|
| 实现方式 | 基于接口 | 基于继承 |
| 性能 | 生成代理快,调用稍慢 | 生成代理慢,调用快 |
| 依赖 | JDK 自带 | 需要引入第三方库 |
| 适用场景 | 代理实现了接口的类 | 代理普通类或 final 方法 |