JDK 动态代理 入门学习
在Java开发中,代理主要有以下三种:
代理类型 | 来源 | 特点 | 依赖 |
---|---|---|---|
JDK 动态代理 | JDK 自带 | 基于接口代理 | 只需要 JDK |
CGLIB 动态代理 | 第三方库 | 基于继承代理 | 需要引入 cglib.jar |
AspectJ 静态代理 | 第三方库 | 编译时织入 | 需要特殊编译器 |
下面主要介绍 JDK 动态代理。
JDK 动态代理(基于接口)有 4 个核心角色,缺一不可:
- 目标接口:代理类和目标类必须实现的接口(如
UserService
); - 目标类:被代理的类(如
UserServiceImpl
,实现UserService
); - InvocationHandler(调用处理器):核心!封装 “增强逻辑” 和 “目标方法调用”,代理对象的所有方法调用都会转发到这里;
- Proxy 类:JDK 提供的工具类,用于动态生成代理对象(无需手动写代理类)。
示例:给方法加日志增强
需求:为UserService
的addUser()
方法添加日志 —— 方法执行前打印 “开始执行 addUser”,执行后打印 “执行 addUser 结束”。
步骤 1:定义目标接口UserService
public interface UserService {
// 目标方法:添加用户
void addUser(String username);
}
步骤 2:实现目标类UserServiceImpl
public class UserServiceImpl implements UserService {
@Override
public void addUser(String username) {
// 目标方法核心逻辑
System.out.println("添加用户:" + username);
}
}
步骤 3:编写 InvocationHandler(核心增强逻辑)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class LogInvocationHandler implements InvocationHandler {
// 目标对象(被代理的对象,通过构造器传入)
private Object target;
// 构造器:接收目标对象
public LogInvocationHandler(Object target) {
this.target = target;
}
/**
* 代理对象的所有方法调用都会触发此方法
* @param proxy 代理对象(一般不用)
* @param method 当前调用的目标方法(如addUser)
* @param args 目标方法的参数(如username)
* @return 目标方法的返回值(无返回则为null)
* @throws Throwable 目标方法可能抛出的异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 1. 前置增强:方法执行前的逻辑(日志记录)
System.out.println("【日志】开始执行方法:" + method.getName());
// 2. 调用目标方法(核心!通过反射调用目标对象的方法)
Object result = method.invoke(target, args); // 此处target是UserServiceImpl实例
// 3. 后置增强:方法执行后的逻辑(日志记录)
System.out.println("【日志】结束执行方法:" + method.getName());
// 返回目标方法的结果(无返回则返回null)
return result;
}
}
步骤 4:用 Proxy 类生成代理对象并测试
import java.lang.reflect.Proxy;
public class ProxyTest {
public static void main(String[] args) {
// 1. 创建目标对象(被代理的对象)
UserService target = new UserServiceImpl();
// 2. 创建InvocationHandler实例(传入目标对象)
LogInvocationHandler handler = new LogInvocationHandler(target);
// 3. 动态生成代理对象(核心!Proxy.newProxyInstance())
UserService proxy = (UserService) Proxy.newProxyInstance(
target.getClass().getClassLoader(), // 1. 目标类的类加载器
target.getClass().getInterfaces(), // 2. 目标类实现的所有接口(必须传,JDK代理基于接口)
handler // 3. 调用处理器(增强逻辑)
);
// 4. 调用代理对象的方法(实际会触发handler的invoke())
proxy.addUser("动态代理");
}
}
执行结果:
【日志】开始执行方法:addUser
添加用户:动态代理
【日志】结束执行方法:addUser
- 调用
proxy.addUser()
时,并未直接执行UserServiceImpl
的addUser()
,而是先进入LogInvocationHandler
的invoke()
方法,执行增强逻辑后,再通过反射调用目标方法; - 若要代理
OrderService
,只需创建OrderService
的目标对象,传入同一个LogInvocationHandler
,即可实现日志增强 ——一套增强逻辑,代理所有接口。 - 反射是基础:动态代理生成代理对象、调用目标方法,底层都依赖反射(如
Method.invoke()
);** - 动态代理是反射的高级应用:反射解决 “运行时操作类结构”,动态代理解决 “运行时动态增强方法”,二者结合实现了框架的核心能力(如 Spring 的 IOC 和 AOP)。
分类:
Java-Backend
标签:
Java
版权申明
本文系作者 @xiin 原创发布在To Future$站点。未经许可,禁止转载。
暂无评论数据