Java 动态代理实现
- 一、JDK动态代理
- 二、CGLIB动态代理
- 三、动态代理的应用场景
- 四、JDK代理与CGLIB代理比较
动态代理是Java中一种强大的技术,它允许在运行时创建代理对象,用于拦截对目标对象的方法调用。
一、JDK动态代理
JDK动态代理是Java标准库提供的代理实现,基于接口。
- 定义接口
interface UserService {
void addUser(String name);
}
- 实现接口
class UserServiceImpl implements UserService {
@Override
public void addUser(String name) {
System.out.println("添加用户" + name);
}
}
- 实现InvocationHandler
class UserServiceInvocationHandler implements InvocationHandler {
private Object target;
public UserServiceInvocationHandler(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;
}
}
- 创建代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxyDemo {
public static void main(String[] args) {
UserService userService = new UserServiceImpl();
UserServiceInvocationHandler invocationHandler = new UserServiceInvocationHandler(userService);
UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
userService.getClass().getInterfaces(), invocationHandler);
proxy.addUser("张三");
}
}
二、CGLIB动态代理
当目标类没有实现接口时,可以使用CGLIB库实现动态代理。
- 添加CGLIB依赖(Maven)
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
- 目标类(不需要实现接口)
class ProductService {
public void addProduct(String name) {
System.out.println("添加产品: " + name);
}
}
- 方法拦截器
class ProductMethodInterceptor 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;
}
}
- 创建代理
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibProxyDemo {
public static void main(String[] args) {
ProductMethodInterceptor interceptor = new ProductMethodInterceptor();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(ProductService.class);
enhancer.setCallback(interceptor);
ProductService proxy = (ProductService) enhancer.create();
proxy.addProduct("手机");
}
}
三、动态代理的应用场景
- AOP编程:如Spring的AOP功能
- 远程方法调用:如RPC框架
- 事务管理
- 日志记录
- 权限控制
- 性能监控
四、JDK代理与CGLIB代理比较
特性 | JDK动态代理 | CGLIB动态代理 |
---|---|---|
基于 | 接口 | 类 |
性能 | 创建快,运行慢 | 创建慢,运行快 |
限制 | 只能代理接口 | 不能代理final类和方法 |
依赖 | Java内置 | 需要第三方库 |
实现原理 | 反射 | 字节码生成 |
在Spring框架中,如果目标对象实现了接口,默认使用JDK动态代理,否则使用CGLIB代理。