Java开发中常用的动态代理方案:JDK代理和CGLib代理比较分析
Java开发中常用的动态代理方案:JDK代理和CGLib代理比较分析
动态代理是一种在运行时生成代理对象的技术,可以在不修改原始代码的情况下,通过代理对象来增强原始对象的功能。在Java开发中,常用的动态代理方案有JDK代理和CGLib代理。两者在实现上有所不同,下面将对这两种动态代理方案进行比较分析。
1. JDK代理
JDK代理是Java自带的动态代理方案,使用Java自带的`java.lang.reflect`包中的`Proxy`和`InvocationHandler`类来实现。JDK代理只能代理接口,需要通过接口生成代理对象。它的原理是在运行时动态生成一个实现了目标接口的代理类,并通过代理类调用目标对象的方法。
以下是一个使用JDK代理的示例代码:
// 定义目标接口
public interface UserService {
void addUser(String username, String password);
}
// 实现目标接口的原始类
public class UserServiceImpl implements UserService {
public void addUser(String username, String password) {
System.out.println("添加用户:" + username + ", 密码:" + password);
}
}
// 自定义InvocationHandler实现类
public class MyInvocationHandler implements InvocationHandler {
private Object target;
public MyInvocationHandler(Object target) {
this.target = target;
}
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 class Main {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
MyInvocationHandler invocationHandler = new MyInvocationHandler(userService);
UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(), invocationHandler);
proxy.addUser("admin", "123456");
}
}
2. CGLib代理
CGLib代理是基于第三方库CGLib实现的动态代理方案。CGLib是一个强大的高性能字节码生成库,它可以在运行时动态生成目标类的子类,并重写目标类的方法来实现代理功能。CGLib代理不需要目标对象实现接口,因此可以代理普通类。
以下是一个使用CGLib代理的示例代码:
// 目标类
public class UserService {
public void addUser(String username, String password) {
System.out.println("添加用户:" + username + ", 密码:" + password);
}
}
// 自定义MethodInterceptor实现类
public class MyInterceptor implements MethodInterceptor {
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 class Main {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserService.class);
enhancer.setCallback(new MyInterceptor());
UserService proxy = (UserService) enhancer.create();
proxy.addUser("admin", "123456");
}
}
JDK代理和CGLib代理的比较分析如下:
1. JDK代理只能代理接口,而CGLib代理可以代理普通类。
2. JDK代理在运行时动态生成一个实现了目标接口的代理类,而CGLib代理在运行时动态生成目标类的子类。
3. JDK代理通过`InvocationHandler`实现类来处理代理逻辑,而CGLib代理通过`MethodInterceptor`实现类来处理代理逻辑。
4. JDK代理生成的代理类比较简单,执行效率较高,但限制了代理的范围;而CGLib代理生成的代理类代码较复杂,执行效率相对较低,但可以代理更广范围的目标类。
综上所述,根据具体需求选择合适的动态代理方案。如果需要代理普通类或不想依赖第三方库,可以选择JDK代理;如果需要代理接口或广泛应用在AOP等场景中,可以选择CGLib代理。