Java 动态代理实现
- 一、JDK动态代理
- 二、CGLIB动态代理
- 三、动态代理的应用场景
- 四、JDK代理与CGLIB代理比较
动态代理是Java中一种强大的技术,它允许在运行时创建代理对象,用于拦截对目标对象的方法调用。
一、JDK动态代理
JDK动态代理是Java标准库提供的代理实现,基于接口。
- 定义接口
interface UserService {void addUser(String name);
}
- 实现接口
class UserServiceImpl implements UserService {@Overridepublic void addUser(String name) {System.out.println("添加用户" + name);}
}
- 实现InvocationHandler
class UserServiceInvocationHandler implements InvocationHandler {private Object target;public UserServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic 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 {@Overridepublic 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代理。