关键词:
动态代理、被代理类、动态代理类、InvocationHandler接口、Proxy类
关键词说明:
动态代理 - 本文讲解的主角,本文中的动态代理指的是JDK的动态代理。动态代理相对于静态代理,后者指的是在编译器就已经确定的代理关系,前者指的是编译器虚拟机不知道具体的代理关系,只有在运行期的时候才根据代码知道具体的代理关系。
被代理类 - 实现公共接口的类(JDK的动态代理是针对接口的代理,没有公共接口是无法实现JDK代理的),实现公共接口的方法。是通过动态代理类实际代理执行方法的类。
动态代理类 - 通过实现InvocationHandler接口的invoke方法来调用被代理类的方法。动态代理类相对于静态代理类优势在于通过反射机制调用方法。不在动态代理类中实现具体的代理关系。
InvocationHandler接口 - 实现动态代理的核心接口,该接口只有Object invoke(Object proxy, Method method, Object[] args)一个方法。在该方法中通过反射机制调用方法。
Proxy类 - 创建对象,通过对象调用方法进入动态代理类invoke方法调用目标方法。
首先看一个动态代理的例子:
公共接口
package com.知识点收集.代理.动态代理;
public interface Person {
public void sayHi(String str, int age);
public void sayHello(String str, int age);
}
实现公共接口的被代理类
package com.知识点收集.代理.动态代理;
public class Student implements Person{
@Override
public void sayHi(String str, int age) {
System.out.println("Student.sayHi " + str + ", " + age);
}
@Override
public void sayHello(String str, int age) {
System.out.println("Student.sayHello " + str + ", " + age);
}
}
动态代理类
package com.知识点收集.代理.动态代理;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class 动态代理类 implements InvocationHandler{
private Object obj;
public 动态代理类(Object obj){
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("动态代理类 invoke begin");
System.out.println("ClassName:" + proxy.getClass().getName());
System.out.println("MethodName:" + method.getName());
for(Object o : args){
System.out.println("arg:" + o);
}
//通过反射调用被代理类的方法
method.invoke(obj, args);
System.out.println("动态代理类 invoke end");
return null;
}
}
Test类
package com.知识点收集.代理.动态代理;
import java.lang.reflect.Proxy;
public class 动态代理Test {
public static void main(String[] args) {
Student s = new Student();
Class clazz = s.getClass();
//创建动态代理类
动态代理类 h = new 动态代理类(s);
//生成对象
Person proxy = (Person)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), h);
//通过代理类调用 被代理类的方法
proxy.sayHello("hello", 100);
System.out.println("end");
}
}
输出结果
动态代理类 invoke begin
ClassName:com.sun.proxy.$Proxy0
MethodName:sayHello
arg:hello
arg:100
Student.sayHello hello, 100
动态代理类 invoke end
end