Java动态代理是一种在运行时动态创建代理对象的技术。它可以让我们在不修改原始代码的情况下,对原始对象进行增强或者添加额外的行为。这种代理方式可以用于很多场景,例如AOP编程、RPC框架等。动态代理是基于Java反射机制实现的,它允许程序在运行时动态地获取类的信息,并且可以在运行时动态地创建对象、调用方法等。
首先需要准备一个接口和实体类
public class Student {
private DoSomeThing doSomeThing;
// ...省略 Getter 和 Setter
}
public interface DoSomeThing {
default void eat() {
System.out.println("吃\n");
}
default void drink() {
System.out.println("喝\n");
}
default void run() {
System.out.println("跑\n");
}
}
接着就可以来对 Student 实体类中的 DoSomeThing 接口进行动态代理了:
public static void main(String[] args) throws Exception {
Student student = new Student();
student.setDoSomeThing(new DoSomeThing() {});
hookStudent(student);
student.getDoSomeThing().eat();
student.getDoSomeThing().drink();
student.getDoSomeThing().run();
}
private static void hookStudent(Student student) throws Exception {
Class studentClass = student.getClass();
Field field = studentClass.getDeclaredField("doSomeThing");
field.setAccessible(true);
Object doSomeThingObj = field.get(student); // 接口实体,后面用来保证 代理后能执行原本的方法
Object proxy = Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{DoSomeThing.class}, // 代理目标类,要求是未实现的接口,否则会报错
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 代理成功后,每调用一次接口函数都会走一遍 invoke()
// 且携带方法信息和方法参数,这样子就可以对 指定方法 做判断和处理了
System.out.println("调用invoke函数");
return method.invoke(doSomeThingObj, args); // 执行原本的方法
}
});
field.set(student, proxy); // 将实体类中的 接口对象 替换为 代理对象
}
首先初始化了 实体类(Student)和接口参数,再对 实体类 中的接口参数进行 动态代理 ,俗称AOP切面编程。代理后每使用一次接口参数中的方法就会调用一次invoke方法, invoke 方法中携带了方法和参数信息,开发者可以对此进行 条件判断和处理。最后,执行接口原来的方法。
执行结果: