1、在使用jdk动态代理的时候,必须要实现InvocationHandler接口
public class JdkInvocationHandler implements InvocationHandler { /** * 被代理对象,目标对象 */ private Object target; public JdkInvocationHandler(Object target){ this.target = target; } /** * * @param proxy 代理类对象 * @param method 被代理执行的方法 * @param args 目标方法参数 * @return 防止执行的返回值 * @throws Throwable */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("日志收集开始。。。"); Object result = method.invoke(target, args); System.out.println("日志收集结束。。。"); return result; } /** * 生成代理类对象 * @param <T> * @return */ public <T> T getProxy(){ return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces() , this); } }2、使用jdk动态代理获取代理类对象(JDK自动生成代理类) $Proxy0.class,使用反编译工具
1.自定义MyExtJdkInvocationHandler接口 ——相当于InvocationHandler
public interface MyExtJdkInvocationHandler { /** * * @param proxy 代理类 * @param method 被代理执行的方法 * @param args 参数 * @return * @throws Throwable */ Object invoke(Object proxy, Method method,Object[] args) throws Throwable; }2.写一个MyJdkInvocationHandler实现MyJdkInvocationHandler接口
public class MyJdkInvocationHandler implements MyExtJdkInvocationHandler { private Object target; public MyJdkInvocationHandler(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("纯手写jdk动态代理开始。。。"); Object result = method.invoke(target,args); System.out.println("纯手写jdk动态代理开始。。。"); return result; } }service层
public interface OrderService { void order() throws Throwable; } public class OrderServiceImpl implements OrderService { public void order() { System.out.println("执行订单操作。。。"); } }3.对比反编译$Proxy0.class来写$Proxy0
public class $Proxy0 implements OrderService { private MyExtJdkInvocationHandler handler; public $Proxy0(MyExtJdkInvocationHandler handler){ this.handler = handler; } public void order() throws Throwable { Method orderMethod = OrderService.class.getMethod("order", new Class[]{}); this.handler.invoke(this, orderMethod, null); } }4、测试
public class TestClient { public static void main(String[] args) throws Throwable { $Proxy0 proxy = new $Proxy0(new MyJdkInvocationHandler(new OrderServiceImpl())); proxy.order(); } }5、打印结果
纯手写jdk动态代理开始。。。 执行订单操作。。。 纯手写jdk动态代理开始。。。我们只需要将V1.0中的$Proxy0类变成动态生成就可以了。
1.看Proxy怎么实现的newProxyInstance
2.实现自己的MyProxy
package com.xwhy; import com.xwhy.ext.proxy.JavaClassLoader; import com.xwhy.ext.proxy.MyExtJdkInvocationHandler; import com.xwhy.service.OrderService; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; import java.io.File; import java.io.FileWriter; import java.lang.reflect.Constructor; import java.lang.reflect.Method; /** * @description: ${description} * @author: Mark * @create: 2019-05-26 16:02:40 **/ public class MyProxy { private static String rt = "\r\t"; public static Object newProxyInstance(JavaClassLoader javaClassLoader, Class<?> classInfo, MyExtJdkInvocationHandler h) { try { //1、拼接代理类源代码 Method[] methods = classInfo.getMethods(); String proxyClass = "package com.xwhy.ext.proxy;" + rt + "import java.lang.reflect.Method;" + rt + "import com.xwhy.ext.proxy.MyExtJdkInvocationHandler;" + rt + "public class $Proxy0 implements " + classInfo.getName() + "{" + rt + "MyExtJdkInvocationHandler h;" + rt + "public $Proxy0(MyExtJdkInvocationHandler h)" + "{" + rt + "this.h= h;" + rt + "}" + getMethodString(methods, classInfo) + rt + "}"; // 2. 写入到到本地文件中.. String filename = "/Users/mark/$Proxy0.java"; File f = new File(filename); FileWriter fw = new FileWriter(f); fw.write(proxyClass); fw.flush(); fw.close(); // 3. 将源代码编译成class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager fileMgr = compiler.getStandardFileManager(null, null, null); Iterable units = fileMgr.getJavaFileObjects(filename); JavaCompiler.CompilationTask t = compiler.getTask(null, fileMgr, null, null, null, units); t.call(); fileMgr.close(); // 4.使用ClassLoader加载到内存 Class<?> $Proxy0 = javaClassLoader.findClass("$Proxy0"); // 5.执行初始化又参构造函数 Constructor<?> constructor = $Proxy0.getConstructor(MyExtJdkInvocationHandler.class); Object o = constructor.newInstance(h); return o; } catch (Exception e) { e.printStackTrace(); } return null; } public static String getMethodString(Method[] methods, Class intf) { String proxyMe = ""; for (Method method : methods) { proxyMe += "public void " + method.getName() + "() throws Throwable {" + rt + "Method md= " + intf.getName() + ".class.getMethod(\"" + method.getName() + "\",new Class[]{});" + rt + "this.h.invoke(this,md,null);" + rt + "}" + rt; } return proxyMe; } public static void main(String[] args) { newProxyInstance(null, OrderService.class, null); } }3.实现自己的ClassLoader
package com.xwhy.ext.proxy; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; public class JavaClassLoader extends ClassLoader { private File classPathFile; public JavaClassLoader(){ // String classPath=JavaClassLoader.class.getResource("").getPath(); String classPath="/Users/mark"; this.classPathFile=new File(classPath); } @Override public Class<?> findClass(String name) throws ClassNotFoundException { String className= JavaClassLoader.class.getPackage().getName()+"."+name; if(classPathFile!=null){ File classFile=new File(classPathFile,name.replaceAll("\\.","/")+".class"); if(classFile.exists()){ FileInputStream in=null; ByteArrayOutputStream out=null; try { in=new FileInputStream(classFile); out=new ByteArrayOutputStream(); byte[] buff=new byte[1024]; int len; while ((len=in.read(buff))!=-1){ out.write(buff,0,len); } return defineClass(className,out.toByteArray(),0,out.size()); }catch (Exception e){ e.printStackTrace(); }finally { if(in!=null){ try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if(out!=null){ try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } } return null; } }4.测试
public class TestClient { public static void main(String[] args) throws Throwable { OrderService orderService = (OrderService) MyProxy.newProxyInstance(new JavaClassLoader(),OrderService.class, new MyJdkInvocationHandler(new OrderServiceImpl())); orderService.order(); } }生成的$Proxy0.class文件如下: 运行时生成的$Proxy0.java文件如下:
package com.xwhy; import java.lang.reflect.Method; import com.xwhy.ext.proxy.MyExtJdkInvocationHandler; public class $Proxy0 implements com.xwhy.service.OrderService { MyExtJdkInvocationHandler h; public $Proxy0(MyExtJdkInvocationHandler h) { this.h = h; } public void order() throws Throwable { Method md = com.xwhy.service.OrderService.class.getMethod("order", new Class[]{}); this.h.invoke(this, md, null); } }5.运行结果
纯手写jdk动态代理开始。。。 执行订单操作。。。 纯手写jdk动态代理开始。。。