这样和妻子解释:Java动态代理机制详解(JDK和CGLIB( 五 )


package com.foo.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {ElectricCar car = new ElectricCar();// 1.获取对应的ClassLoaderClassLoader classLoader = car.getClass().getClassLoader();// 2.获取ElectricCar 所实现的所有接口Class[] interfaces = car.getClass().getInterfaces();// 3.设置一个来自代理传过来的方法调用请求处理器 , 处理所有的代理对象上的方法调用InvocationHandler handler = new InvocationHandlerImpl(car);/*4.根据上面提供的信息 , 创建代理对象 在这个过程中 ,a.JDK会通过根据传入的参数信息动态地在内存中创建和.class 文件等同的字节码b.然后根据相应的字节码转换成对应的class ,c.然后调用newInstance()创建实例*/Object o = Proxy.newProxyInstance(classLoader, interfaces, handler);Vehicle vehicle = (Vehicle) o;vehicle.drive();Rechargable rechargeable = (Rechargable) o;rechargeable.recharge();}}package com.foo.proxy;/*** 交通工具接口* @author louluan*/public interface Vehicle {public void drive();}package com.foo.proxy;/*** 可充电设备接口* @author louluan*/public interface Rechargable {public void recharge();}package com.foo.proxy;/*** 电能车类 , 实现Rechargable , Vehicle接口* @author louluan*/public class ElectricCar implements Rechargable, Vehicle {@Overridepublic void drive() {System.out.println("Electric Car is Moving silently...");}@Overridepublic void recharge() {System.out.println("Electric Car is Recharging...");}}package com.foo.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class InvocationHandlerImpl implements InvocationHandler {private ElectricCar car;public InvocationHandlerImpl(ElectricCar car){this.car=car;}@Overridepublic Object invoke(Object paramObject, Method paramMethod,Object[] paramArrayOfObject) throws Throwable {System.out.println("You are going to invoke "+paramMethod.getName()+" ...");paramMethod.invoke(car, null);System.out.println(paramMethod.getName()+" invocation Has Been finished...");return null;}}来看一下代码执行后的结果:
这样和妻子解释:Java动态代理机制详解(JDK和CGLIB文章插图
生成动态代理类的字节码并且保存到硬盘中:
JDK提供了sun.misc.ProxyGenerator.generateProxyClass(String proxyName,class[] interfaces) 底层方法来产生动态代理类的字节码:
下面定义了一个工具类 , 用来将生成的动态代理类保存到硬盘中:
package com.foo.proxy;import java.io.FileOutputStream;import java.io.IOException;import java.lang.reflect.Proxy;import sun.misc.ProxyGenerator;public class ProxyUtils {/** 将根据类信息 动态生成的二进制字节码保存到硬盘中 ,* 默认的是clazz目录下* params :clazz 需要生成动态代理类的类* proxyName : 为动态生成的代理类的名称*/public static void generateClassFile(Class clazz,String proxyName){//根据类信息和提供的代理类名称 , 生成字节码byte[] classFile = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces());String paths = clazz.getResource(".").getPath();System.out.println(paths);FileOutputStream out = null;try {//保留到硬盘中out = new FileOutputStream(paths+proxyName+".class");out.write(classFile);out.flush();} catch (Exception e) {e.printStackTrace();} finally {try {out.close();} catch (IOException e) {e.printStackTrace();}}}}现在我们想将生成的代理类起名为“ElectricCarProxy” , 并保存在硬盘 , 应该使用以下语句:
ProxyUtils.generateClassFile(car.getClass(), "ElectricCarProxy");这样将在ElectricCar.class 同级目录下产生 ElectricCarProxy.class文件 。 用反编译工具如jd-gui.exe 打开 , 将会看到以下信息:
import com.foo.proxy.Rechargable;import com.foo.proxy.Vehicle;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.lang.reflect.UndeclaredThrowableException;/**生成的动态代理类的组织模式是继承Proxy类 , 然后实现需要实现代理的类上的所有接口 , 而在实现的过程中 , 则是通过将所有的方法都交给了InvocationHandler来处理 */public final class ElectricCarProxy extends Proxyimplements Rechargable, Vehicle{private static Method m1;private static Method m3;private static Method m4;private static Method m0;private static Method m2;public ElectricCarProxy(InvocationHandler paramInvocationHandler)throws{super(paramInvocationHandler);}public final boolean equals(Object paramObject)throws{try{ // 方法功能实现交给InvocationHandler处理return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();}catch (Error|RuntimeException localError){throw localError;}catch (Throwable localThrowable){throw new UndeclaredThrowableException(localThrowable);}}public final void recharge()throws{try{// 方法功能实现交给InvocationHandler处理this.h.invoke(this, m3, null);return;}catch (Error|RuntimeException localError){throw localError;}catch (Throwable localThrowable){throw new UndeclaredThrowableException(localThrowable);}}public final void drive()throws{try{// 方法功能实现交给InvocationHandler处理this.h.invoke(this, m4, null);return;}catch (Error|RuntimeException localError){throw localError;}catch (Throwable localThrowable){throw new UndeclaredThrowableException(localThrowable);}}public final int hashCode()throws{try{// 方法功能实现交给InvocationHandler处理return ((Integer)this.h.invoke(this, m0, null)).intValue();}catch (Error|RuntimeException localError){throw localError;}catch (Throwable localThrowable){throw new UndeclaredThrowableException(localThrowable);}}public final String toString()throws{try{// 方法功能实现交给InvocationHandler处理return (String)this.h.invoke(this, m2, null);}catch (Error|RuntimeException localError){throw localError;}catch (Throwable localThrowable){throw new UndeclaredThrowableException(localThrowable);}}static{try{//为每一个需要方法对象 , 当调用相应的方法时 , 分别将方法对象作为参数传递给InvocationHandler处理m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });m3 = Class.forName("com.foo.proxy.Rechargable").getMethod("recharge", new Class[0]);m4 = Class.forName("com.foo.proxy.Vehicle").getMethod("drive", new Class[0]);m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);return;}catch (NoSuchMethodException localNoSuchMethodException){throw new NoSuchMethodError(localNoSuchMethodException.getMessage());}catch (ClassNotFoundException localClassNotFoundException){throw new NoClassDefFoundError(localClassNotFoundException.getMessage());}}}