-
JDK版本为RedHat OpenJDK 1.8.0_282。
-
JDK中的动态代理Proxy类仅限于方法拦截,且只能代理实现了接口的对象。
-
调用Proxy的静态方法创建——继承了Proxy类的代理类(java只支持单继承,这就是为什么要求被代理类必须实现接口),通过该代理类的构造器创建对应代理对象,该对象实现了被代理类的接口,仅起到接口的作用。
-
代理类对象内持有一个——实现了InvocationHandler接口的对象(我们称它为中间对象吧)的引用,中间对象又持有一个被代理对象的引用。中间对象是真正办事的对象,对代理类对象的所有方法调用都会转发给中间对象,由中间对象的invoke方法实现,而中间对象的 invoke 方法,通过反射调用了被代理对象的对应方法。
-
以上是从整体的角度介绍,下面从介绍下具体代码。
interface Animal{ public void speak(); } class Dog implements Animal{ @Override public void speak() { System.out.println("I am a dog."); } } class DogHandler implements InvocationHandler{ private Object obj; public dogHandler(Object obj){ this.obj = obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("In a handler."); method.invoke(obj, args); System.out.println(obj.toString()); return proxy; } } public class test { public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Dog aDog = new Dog(); DogHandler h = new DogHandler(aDog); // Animal pxyDog = (Animal) Proxy.newProxyInstance(dog.class.getClassLoader(), // dog.class.getInterfaces(), h); Class pxyDogClazz = Proxy.getProxyClass(Dog.class.getClassLoader(), Dog.class.getInterfaces()); Constructor pxyDogCons = pxyDogClazz.getConstructor(InvocationHandler.class); Animal pxyDog = (Animal) pxyDogCons.newInstance(h); pxyDog.speak(); } }
-
Proxy提供了两种方式创建代理对象,getProxyClass()创建代理类 + getConstructor() 反射获取构造器对象 + newInstance()创建实例,以及将其与对应对应异常处理代码打包在一块的,newProxyInstance()。
-
getProxyClass() 接受类加载器与接口类型,实质是在内部调用getProxyClass0(),而后者则是向内部成员 proxyClassCache 申请,proxyClassCache 是一个缓存,如果之前创建过对应的代理类,则直接返回,否则创建。