万字解读Java的动态代理
在Java中,动态代理是一种在运行时创建代理对象的技术。在许多场景中,动态代理能够极大地简化代码的编写,并且增强系统的灵活性和可扩展性。Java的动态代理主要有两种实现方式:JDK原生动态代理和CGLIB动态代理。本文将对这两种实现方式进行详细解读,并给出代码示例。
一、JDK原生动态代理
JDK的动态代理主要依赖于java.lang.reflect.Proxy
类和InvocationHandler
接口。它要求被代理的类实现一个或多个接口。
1. 创建接口和实现类
首先,我们定义一个接口和实现类:
public interface UserService {
void addUser(String username);
}
public class UserServiceImpl implements UserService {
@Override
public void addUser(String username) {
System.out.println("用户 " + username + " 被添加了");
}
}
2. 创建InvocationHandler
我们需要一个InvocationHandler
来处理代理对象的调用:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public 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("方法 " + method.getName() + " 被调用");
return method.invoke(target, args);
}
}
3. 创建代理对象
使用Proxy.newProxyInstance
方法来创建动态代理对象:
import java.lang.reflect.Proxy;
public class DynamicProxyTest {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
MyInvocationHandler handler = new MyInvocationHandler(userService);
UserService proxyInstance = (UserService) Proxy.newProxyInstance(
userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(),
handler);
proxyInstance.addUser("张三");
}
}
4. 运行结果
运行上面的代码,输出如下:
方法 addUser 被调用
用户 张三 被添加了
二、CGLIB动态代理
CGLIB(Code Generation Library)是一个功能强大的高效的代码生成库,它可以在运行时动态生成某个类的子类,从而实现代理。与JDK的动态代理不同,CGLIB不需要被代理的类实现任何接口。
1. 创建目标类
我们定义一个普通类而非接口:
public class OrderService {
public void createOrder(String orderName) {
System.out.println("订单 " + orderName + " 被创建了");
}
}
2. 创建MethodInterceptor
我们需要实现MethodInterceptor
接口:
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.Enhancer;
public class MyMethodInterceptor implements MethodInterceptor {
@Override
public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
net.sf.cglib.proxy.MethodProxy proxy) throws Throwable {
System.out.println("方法 " + method.getName() + " 被调用");
return proxy.invokeSuper(obj, args);
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(OrderService.class);
enhancer.setCallback(new MyMethodInterceptor());
OrderService proxyInstance = (OrderService) enhancer.create();
proxyInstance.createOrder("订单1");
}
}
3. 运行结果
运行代码,将输出:
方法 createOrder 被调用
订单 订单1 被创建了
三、总结
在这篇文章中,我们深入探讨了Java的动态代理,包括JDK原生动态代理和CGLIB动态代理的实现方式与示例代码。JDK动态代理更为常用,但受到限制,只能代理实现了接口的类。而CGLIB则没有这个限制,能够代理任何类型的类,通常比JDK动态代理执行速度快,但也因此引入了更多内存消耗。
选择使用哪种动态代理方式,通常取决于具体的使用场景及需求。希望通过本文的讲解,读者能够对Java的动态代理有更深的理解。